当前位置: 首页 > news >正文

Spring DI和AOP简介

        Spring可以做很多事情,它为企业级开发提供了丰富的功能,但是这些功能的底层都依赖于它的两个核心特性,也就是依赖注入(dependency injection,DI)面向切面编程(aspect-oriented programming,AOP)。

一、依赖注入

1.构造注入

考虑下面程序展现的Knight类:

package sia.knights;

public class DamselRescuingKnight implements Knight {

  private RescueDamselQuest quest;

  public DamselRescuingKnight() {
    //将DamselRescuingKnightRescueDamselQuest紧耦合
    this.quest = new RescueDamselQuest();
  }

  public void embarkOnQuest() {
    quest.embark();
  }
}

         可以看到,DamselRescuingKnight在它的构造函数中自行创建了RescueDamselQuest。这使得DamselRescuingKnight紧密地和RescueDamselQuest耦合到一起了,因此极大地限制了这个骑士执行探险的能力。如果一个少女需要救援,这个骑士能够召之即来。但是如果一条恶龙需要杀掉,或者让一个圆桌滚起来,那么这个骑士就爱莫能助了。

我们再定义一个Knight类:

package sia.knights;
  
public class BraveKnight implements Knight {

  private Quest quest;

  //通过构造函数将Quest注入进来
  public BraveKnight(Quest quest) {
    this.quest = quest;
  }

  public void embarkOnQuest() {
    quest.embark();
  }
}

        我们可以看到不同于之前的DamselRescuingKnightBraveKnight 没有自行创建探险任务,而是在构造的时候把探险任务作为构造器参数传入。这是依赖注入的方式之一,即构造器注入(constructor injection)

        更重要的是,传入的探险类型是Quest,也就是所有探险任务都必须实现一个接口。所以,BraveKnight 能够响应RescueDamselQuest(少女救援请求)、SlayDragonQuest(屠杀恶龙请求)、MakeRoundTableRounderQuest(圆桌滚起来请求)等任意的Quest实现。

2.完整依赖注入举例

BraveKnight.java:

package sia.knights;
  
public class BraveKnight implements Knight {

  private Quest quest;

  //通过构造函数将Quest注入进来
  public BraveKnight(Quest quest) {
    this.quest = quest;
  }

  public void embarkOnQuest() {
    quest.embark();
  }
}

SlayDragonQuest.java:

package sia.knights;

import java.io.PrintStream;

public class SlayDragonQuest implements Quest {

  private PrintStream stream;

  public SlayDragonQuest(PrintStream stream) {
    this.stream = stream;
  }

  public void embark() {
    stream.println("Embarking on quest to slay the dragon!");
  }
}

knight.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="knight" class="sia.knights.BraveKnight">
  <!--注入Quest bean-->
  <constructor-arg ref="quest" />
</bean>

<!--创建SlayDragonQuest-->
<bean id="quest" class="sia.knights.SlayDragonQuest">
  <constructor-arg value="#{T(System).out}" />
</bean>

</beans>

KnightConfig.java:

package sia.knights.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import sia.knights.BraveKnight;
import sia.knights.Knight;
import sia.knights.Quest;
import sia.knights.SlayDragonQuest;

@Configuration
public class KnightConfig {

  @Bean
  public Knight knight() {
    return new BraveKnight(quest());
  }
  
  @Bean
  public Quest quest() {
    return new SlayDragonQuest(System.out);
  }

}

KnightMain.java:

package sia.knights;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class KnightMain {

  public static void main(String[] args) throws Exception {
    //加载Spring上下文
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring/knight.xml");
    //获取knight bean
    Knight knight = context.getBean(Knight.class);
    //使用knight
    knight.embarkOnQuest();
    context.close();
  }
}

流程梳理如下图: 

 二、应用切面

相关文章:

  • 以太坊改造完成,矿工要失业了?
  • dubbo拓展点机制(和对JDK SPI机制的优化)
  • HTML常用标签积累
  • 【一起学SQLite】--SQLite中一些与众不同的特性?(2-1)
  • A+文档丨Azure MySQL 数据库高可用性解析
  • 【Python基础】Numpy:切片和索引操作
  • 【PAT甲级】1004 Counting Leaves
  • 【Vue】vue基础学习笔记
  • 边缘检测算子之间的优劣
  • 在软件测试摸爬滚打了8年,失业半年了。offer你在哪儿呀!
  • 15分钟了解sql注入(一) union注入
  • 基于混沌映射与差分进化自适应教与学优化算法-附代码
  • nginx基本使用一 ——————反向代理、负载均衡
  • 通讯录管理系统精解
  • 线上展厅表现形式 广州商迪
  • 分享的文章《人生如棋》
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • CSS3 变换
  • hadoop入门学习教程--DKHadoop完整安装步骤
  • Java 最常见的 200+ 面试题:面试必备
  • log4j2输出到kafka
  • Netty源码解析1-Buffer
  • php的插入排序,通过双层for循环
  • Promise初体验
  • quasar-framework cnodejs社区
  • Spring Boot快速入门(一):Hello Spring Boot
  • Vue UI框架库开发介绍
  • 当SetTimeout遇到了字符串
  • 缓存与缓冲
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 如何优雅地使用 Sublime Text
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • 用简单代码看卷积组块发展
  • 正则表达式小结
  • 转载:[译] 内容加速黑科技趣谈
  • 【干货分享】dos命令大全
  • Java总结 - String - 这篇请使劲喷我
  • ​io --- 处理流的核心工具​
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • ​批处理文件中的errorlevel用法
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • (ibm)Java 语言的 XPath API
  • (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
  • .NET CF命令行调试器MDbg入门(一)
  • .NET gRPC 和RESTful简单对比
  • .skip() 和 .only() 的使用
  • /使用匿名内部类来复写Handler当中的handlerMessage()方法
  • [ vulhub漏洞复现篇 ] Celery <4.0 Redis未授权访问+Pickle反序列化利用
  • [2016.7.test1] T2 偷天换日 [codevs 1163 访问艺术馆(类似)]
  • [Android实例] 保持屏幕长亮的两种方法 [转]
  • [AutoSar]工程中的cpuload陷阱(三)测试
  • [bzoj 3534][Sdoi2014] 重建