Spring的非侵入性–基于Java的容器配置介绍
一、Spring框架的非侵入性
1.前言
在上一篇博文中讲到,Spring允许以非侵入方式使用注解,无需接触目标组件的源代码。 要想真正理解这句话,我们就有必要先弄清楚非侵入式设计的概念了。
2.侵入式与非侵入式
- 侵入式:代码结构要与所使用的技术产生依赖。
- 非侵入式:使用一个新的技术不会或者基本不改变原有代码结构,原有代码不作任何修改即可。
3.侵入式框架与非侵入式框架
-
侵入式框架:引入了框架,对现有的类的结构有影响,需要实现框架某些接口或者基础某些特定的类。
- 优点:侵入式可以使得用户的代码与框架更好的结合,充分利用框架提供的功能。
- 缺点:侵入式让用户的代码对框架产生了依赖,不利于代码的复用,当去除框架的时候,程序就无法运行。
- 例子:Struts1框架, Struts1代码严重依赖于Struts1 API,属于侵入性框架。
-
非侵入式框架:引入了框架,对现有的类结构没有影响,不需要实现框架某些接口或者特定的类。
- 优点:代码对框架没有过多的依赖,允许所开发出来的应用系统能够在不用的环境中自由移植,不需要修改应用系统中的核心功能实现的代码
- 缺点:无法复用框架提供的代码和功能
- 例子:Spring框架,通过配置完成依赖注入就可以使用,当我们想换个框架,只需要修改相应的配置,程序仍然可以运行。
二、在Java代码中使用注解来配置容器
1.基础概念:@Bean
和@Configuration
由@Configuration
修饰的类和由@Bean
修饰的方法组成了Spring Java配置的主要构件。
@Bean
注解用于方法实例化,配置和初始化要由Spring IoC容器管理的对象。 使用的时候,@Bean
注解的方法,所在的类需要用@Configuration
来修饰,表示该类是作为Bean定义的来源,容器初始化时,需要扫描该类,进行自动装配。
用@Configuration
注解的类,表示该类的主要目的是作为Bean定义的来源。 此外,@Configuration
类允许通过调用同一类中的其他@Bean
方法来定义Bean间的依赖关系。 最简单的@Configuration
类的内容如下:
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
2. @Component
和@Bean
的区别
@Component和@Bean都可以定义bean,但实际上@Component
和@Bean
是做两个完全不同的事情,不应该混为一谈,具体比较如下:
@Component
(和@Service
和@Repository
)用于自动检测和使用类路径扫描自动配置bean。 注释类和bean之间存在隐式的一对一映射(即每个类一个bean)。这种方法对需要进行逻辑处理的控制非常有限,因为它纯粹是声明性的。@Bean
用于显式声明单个bean,而不是让Spring像上面那样自动执行它。它将bean的声明与类定义分离,并允许您精确地创建和配置bean。
那我们在什么时候会使用@Bean
?假设下,某天你想创建一个第三方的组件,但是你没有源代码,也就没办法使用@Component
进行自动配置,这种时候使用@Bean
就比较合适了。 又比如,具体采用哪个实现是依赖于某些参数的,在这种情况下@Bean
无疑是更合适的选择。 示例如下:
@Bean
@Scope("prototype")
public SomeService someService(String state) {
switch (state) {
case 1:
return new Impl1();
case 2:
return new Impl2();
case 3:
return new Impl3();
default:
return new Impl();
}
}
3.使用AnnotationConfigApplicationContext实例化Spring容器
以下各节介绍了Spring 3.0中引入的AnnotationConfigApplicationContext
。 这种通用的ApplicationContext
实现,不仅能够接受@Configuration
类作为输入,而且还可以接受普通的@Component
类和带有JSR-330元数据注释的类。
- 当提供
@Configuration
类作为输入时,@Configuration
类本身将注册为Bean定义,并且该类中所有已声明的@Bean
方法也将注册为Bean定义。 - 提供
@Component
和JSR-330类时,它们将注册为bean定义,并且假定在必要时在这些类中使用了诸如@Autowired
或@Inject
之类的DI元数据。
(1)作为AnnotationConfigApplicationContext
构造函数的参数
将@Configuration类
用作输入,实例化AnnotationConfigApplicationContext
,使得Spring容器的使用,完全不依赖XML。 如下面的示例所示: