Spring Bean的注册与发现

作为J2EE核心框架的 Spring,其最基本的一项职能是管理bean,即管理Java对象。在 Spring 的概念中,这个管理所有bean的大管家就是Container。有了Container这个概念,每一个Java类便可以更加独立地存在。创建出来的类A,可以将自己注册进这个container,成为一个bean,供它管理。在此之后,所有用到这个类A的地方,便可以直接向container索取。如此,每个类只需要关心自己的业务逻辑,而不必再费心去构建自己依赖的其它类。每一个类都可以把其它类当做是一个独立的服务,随时可以供自己索取。从而实现整体上各个类之间的解耦。

如上所述,对这个container来讲最重要的有两个工作:一个是提供一种方式,能够让一个Java类把自己注册进container成为一个bean;另一个是提供一种方式,能够让一个Java类A,从container中获取到自己需要的依赖类B。

完成这两个工作,有三种基本的形式:

  • automatic configuration
  • explicit Java-based configuration
  • explicit XML-based configuration

Automatic Configuration

这应该是最为推荐、也作为好用的模式。无论是一个Java类将自己注册进Spring container成为bean,还是从container那里取出自己需要的bean依赖,都非常方便。这两个过程对应的概念为:

  • Component Scanning: tell Spring what classes need to be created as beans.
  • Autowiring: get the matched bean from Spring.
package terence.xie.service;
import org.springframework.stereotype.Component;

@Component
public class TerryCD implements CompactDisc {
    
    private String title = "Your Spring";
    
    private String artist = "Terry";
    
    public void play() {
        System.out.println(String.format("Title = '%s', artist = '%s'", title, artist));
    }
}

这里最重要的是 @Component 这个Java注解(annotation)。这个annotation就向Spring container表征了,我需要被创建为bean。

另一方面,对于container来讲,只是有这个 @Component 还不够。虽然遇到这个annotation就知道要把它创建为bean,但是,我从哪里去搜索这一堆堆的类呢?也即是,对container来讲,它首先需要知道从哪个地方去搜索出一堆备选的Java类,然后再从这堆Java类中一个个地看它们是否被打上了 @Component annotation,进而将其注册为bean。

需要一个单独的类,来说明container应该从什么地方搜索备选类,这就是 XXXConfig.java 的作用。

package terence.xie.config;

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

@Configuration
@ComponentScan(basePackages = "terence.xie")
public class CDConfig {
    
}

对这个类来讲,annotation @Configuration 用于告知container这个类将被当做配置文件处理。虽然它依旧是以Java文件的方式来呈现,但在逻辑上应当只用作提供bean的配置文件,而不应该做其它多余的事情。

在这里,整个 CDConfig 类表面上没有做任何事,但annotation @ComponentScan 告知了Spring container需要从package terence.xie 去寻找是否需要创建为bean的Java类,即寻找被标注为 @Component 的类。

可以看到,无论是 “告知Spring应该被注册为bean” 还是 “从Spring获取依赖的bean” 似乎都没有什么明显的方法。这就是 Autowired 的灵活和方便之处。仅仅依靠 “注解的发现” ,将其他繁琐的发现机制逻辑隐藏于Spring之后,实在是非常优雅。这也是目前最受推荐的注册bean、获取bean的方式。

Explicit Java-based configuration

使用 Automatic Configuration 的机制虽然方便,但在某些特定情况还无法满足开发的需求。例如,你想创建一个第三方的类作为bean,但你又没有权限修改第三方的源码,此时你便无法将 @Component 这个annotation加入到这个第三方类的源码上。这样 Automatic Configuration 的机制便无法使用了。

对这个问题的解决方案是,可以继续使用上面创建的 XXXConfig.java 类。上面的 CDConfig.java 内部并没有任何代码,仅使用了类级别的注解来指定container发现bean的路径。通过增加 @Bean 注解在内部,可以更为灵活地将bean注册进container。

package terence.xie.config;

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

@Configuration
@ComponentScan(basePackages = "terence.xie")
public class CDConfig {
    
	@Bean
    public CompactDisc terryCd() {
        return new TerryCD();
    } 
}

可以看到,这里将 TerryCD 注册进container成为bean,并不需要改动 TerryCD 的源码,也不需要 TerryCD 内部必须有 @Component 存在。这种方式,即是手动、显式地将一个Java类注册进container。

这里 @Bean 的意思是,将返回的类作为一个bean注册进container。至于其返回类的方法 terryCD() 是不重要的,重要的是这个方法的返回值。所以,当你需要将一个类A注册为bean时,你只需要在 XXXConfig.java 中提供一个方法,标记好annotation @Bean ,将其返回类型设定为类型A即可。

Explicit XML-based configuration

Explicit Java-based configuration 很相似的另一种显式声明bean的方式是使用 XML 文件。这里提供它的说明,更多的是处于对 legacy code 的理解。很多第三方的、创建于很早之前的项目,都会以这种方式来注册bean。如果是从零开始,那一定会选择 automatic configuration 或者 explicit java-based configuration 的方式。

<?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
    http://www.springframework.org/schema/context">
    
    <!-- configuration details go here -->
    
</beans>

对, xml-based configuration 会显得有些复杂。上面这个xml给出了一个声明bean的pattern,但其实里面没有任何一个实际的bean声明。也即是说,只要你想要声明bean,你至少得先写下上面这么多的xml代码。

如果要声明一个bean,只需要在其中添加标签 <bean id="compactDisc" class="terence.xie.service.TerryCD" /> 即可:

<?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
    http://www.springframework.org/schema/context">
    
    <!-- configuration details go here -->
    <bean id="compactDisc" class="terence.xie.service.TerryCD" />
    
</beans>

这里的 id 将作为整个bean的名称注册进container,而 class 指定了需要被注册成为bean的类。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值