本系列博客为spring In Action 这本书的学习笔记
上一篇博客中讲了自动化装配Bean, 那么这篇博客就来讲一下第二种装配Bean的方式: 通过Java代码装配Bean.
通过Java代码装配Bean
所谓通过Java代码装配Bean, 就是通过编写JavaConfig文件进行配置, 更简单地来讲, 就是在JavaConfig中声明Bean.
我们先来简单探究一下JavaConfig与一般的Java文件有什么区别.
JavaConfig就是带有@Configuration注解的Java文件. 但严格意义上来讲, JavaConfig并不是Java文件, 它更接近于配置文件. JavaConfig里不包含任何的业务逻辑, 也不应该出现在任何业务逻辑的代码中, 通常情况下, 我们会将所有的JavaConfig放在单独的包中.
使用Java代码显式装配Bean, 其核心就是JavaConfig.
1. 创建JavaConfig
怎样创建JavaConfig呢?
其实关键的就一点, 就是添加@Configuration注解。 在一个Java文件中, 添加了这个注解就说明该Java文件是一个JavaConfig了。
下来先复习一下在前面的代码中, 出现过的JavaConfig.
程序1:在CD播放器器例子中出现过的JavaConfig
@Configuration
@ComponentScan
public class CDPlayerConfig {
}
这个JavaConfig是启用组件扫描的一个配置文件。@ComponentScan标注就是在Spring中使用组件扫描。
这是我们在上一篇自动装配中使用到的JavaConfig, 可能会有人觉得奇怪, JavaConfig不是显式装配Bean的方式吗?为什么在自动装配中也用到了JavaConfig。 那就建议你回头去仔细看看上一篇自动装配那篇博客, 自动装配Bean机制由组件扫描和自动装配两部分组成, 组件扫描仍需要显式配置之后才能发挥它的作用。
好, 那么我们来看一下通过Java代码来装配Bean的JavaConfig应该怎样写。
程序2 : 创建一个普通的JavaConfig
@Configuration
public class CDPlayerConfig {
}
这里是创建了一个JavaConfig, 但是里面还没有声明任何Bean, 也没有什么关于开启组件扫描的标注,我们在下面将会在这个JavaConfig中声明Bean。
2. 声明简单的Bean
所谓在JavaConfig中声明Bean, 就是在JavaConfig中编写一个创建所需类型的实例, 然后给该方法加上@Bean注解。比如下面的代码:
程序3: 声明一个Jay类的Bean
@Bean
public CompactDisc jay(){
return new Jay();
}
在上面的代码中, 该方法返回了一个对象, @Bean标注会告诉Spring要将这个对象注册为Bean.
可能有人不是很理解这句话, 早在Spring学习笔记(一)中我就提到过, Bean就是包装后的Object, 那也就是说, Spring最终会将new Jay()产生的实例包裹起来, 形成Bean。
(1) 给Bean自定义名字
默认情况下, Bean的ID与带有@Bean注解的方法名是一样的。在本例中, Bean的名字将会是jay。如果想要自己给Bean命名的话, 可以通过name属性进行设置。 比如下面的代码:
程序4: 给Bean自定义名字
@Bean(name = "jayzhou")
public CompactDisc jay(){
return new Jay();
}
(2) 充分使用Java的功能来多样化装配Bean
既然是通过Java代码来装配Bean,那么对于程序3而言, 我们完全可以发挥Java的功能, 只需要最后生成一个CompactDisc实例就可以了。比如我们想要随机选择一盘CD来播放:
程序5: 随机播放一盘CD
@Bean
public CompactDisc randomCD(){
int choice = (int)Math.floor(Math.random() * 4);
if(choice == 0){
return new Jay();
}else{
return new Xin();
}
}
3. 使用JavaConfig实现注入
在上一篇Spring学习笔记自动装配中, Spring帮我们来完成了Bean的注入, 那么现在我们要通过Java代码来手动完成装配.
既然我们已经有了CD的Bean, 现在要做的是播放CD, 也就是要将CD注入到CDPlayer中. 通过Java装配Bean有两种方式, 下面我们来注意看一下:
(1) 装配方式一: 通过调用方法来引入Bean
程序5: 创建CDPlayer Bean时直接调用CD Bean.
public CDPlayer cdPlayer(){
return new CDPlayer(jay());
}
在上面的例子中, 与前面提到的在JavaConfig声明Bean类似, cdPlayer()方法返回的CDPlayer对象将被注册成CDPlayer Bean, 但是值得注意的是, 返回的CDPlayer对象调用了jay()方法, 结合前面我们可以知道, 此时的jay()方法返回的Jay对象已经被注册为一个Bean.
所以看起来就像是在创建CDPlayer Bean的时候会调用创建Jay Bean的方法. 但实际上并非如此, cdPlayer()方法调用jay()这个方法的时候, 直接返回jay Bean, 而非每次调用都重新new一个Jay对象再交给Spring注册成一个Bean.
这也就是说, jay Bean在Spring中只存在一份, 如果在这个JavaConfig中还有其它Bean需要用到Jay Bean的时候, 将与CDPlayer Bean共用一份Jay Bean实例, 因为默认情况下, Spring中的Bean都是单例的.
(2) 装配方式二: 自动匹配所需Bean进行装配
我们先来看这种装配方式的代码:
程序6: 自动匹配所需的Bean进行装配
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc){
return new CDPlayer(compactDisc);
}
上面这种装配方式在cdPlayer()方法中请求了一个CompactDisc类型的参数, 也就是说, 请求了一个CompactDisc类型的Bean. 但是, 这里并没有说明它请求的到底是哪一个Bean, 这就有点自动装配的意味了. 在这里, Spring会自动给cdPlayer()方法匹配一个CompactDisc类型的Bean, 甚至这个Bean可以不在这个JavaConfig中, 它可以通过组件扫描或者通过XML进行配置来被这里的cdPlayer()方法使用.
这就是关于使用Java代码来装配Bean的方式, 下一篇我们将继续讨论如何使用XML装配Bean.