七、通过Java代码装配bean

概述

  1. 基于Java类定义Bean配置元数据,其实就是通过Java类定义Spring配置元数据,且直接消除XML配置文件。
  2. 基于Java类定义Bean配置元数据中的@Configuration注解的类等价于XML配置文件,@Bean注解的方法等价于XML配置文件中的Bean定义。
    基于Java类定义Bean配置元数据需要通过
  3. AnnotationConfigApplicationContext加载配置类及初始化容器,类似于XML配置文件需要使用ClassPathXmlApplicationContext加载配置文件及初始化容器。
  4. 基于Java类定义Bean配置元数据需要CGLIB的支持,因此要保证类路径中包括CGLIB的jar包。

定义Bean配置元数据的步骤

1、 通过@Configuration注解需要作为配置的类,表示该类将定义Bean配置元数据;
2、 通过@Bean注解相应的方法,该方法名默认就是Bean名,该方法返回值就是Bean对象;
3、 通过AnnotationConfigApplicationContext或子类加载基于Java类的配置

package cn.javass.spring.chapter12.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration  
public class ApplicationContextConfig {
    @Bean 
    public String message() {
        return "hello";
    }
}


 使用@Bean注解配置类中的方法,该方法名就是Bean的名字,该方法返回值就是Bean对象。
 使用new AnnotationConfigApplicationContext(ApplicationContextConfig.class)
创建应用上下文,构造器参数为使用@Configuration注解的配置类,读取配置类进行实例化相应的Bean。


@Configuration

通过@Configuration注解的类将被作为配置类使用,表示在该类中将定义Bean配置元数据,且使用@Configuration注解的类本身也是一个Bean,使用方式如下所示

import org.springframework.context.annotation.Configuration;
@Configuration("ctxConfig")
public class ApplicationContextConfig {
    //定义Bean配置元数据
}

因为使用@Configuration注解的类本身也是一个Bean,因为@Configuration被@Component注解了,因此@Configuration注解可以指定value属性值,如“ctxConfig”就是该Bean的名字,如使用“ctx.getBean(“ctxConfig”)”将返回该Bean。
使用@Configuration注解的类不能是final的,且应该有一个默认无参构造器。

@Bean

通过@Bean注解配置类中的相应方法,则该方法名默认就是Bean名,该方法返回值就是Bean对象,并定义了Spring IoC容器如何实例化、自动装配、初始化Bean逻辑,具体使用方法如下

@Bean(name={}, 
      autowire=Autowire.NO, 
      initMethod="", 
      destroyMethod="")

 name:指定Bean的名字,可有多个,第一个作为Id,其他作为别名;
 autowire:自动装配,默认no表示不自动装配该Bean,另外还有Autowire.BY_NAME表示根据名字自动装配,Autowire.BY_TYPE表示根据类型自动装配;
 initMethod和destroyMethod:指定Bean的初始化和销毁方法。

@Bean 
public String message() {
    return new String("hello");
}

等价于

<bean id="message" class="java.lang.String">
<constructor-arg index="0" value="hello"/>
</bean>

使用@Bean注解的方法不能是private、final或static的

@Import

类似于基于XML配置中的,基于Java的配置方式提供了@Import来组合模块化的配置类,使用方式如下所示:

package cn.javass.spring.chapter12.configuration;
//省略import
@Configuration("ctxConfig2")
@Import({ApplicationContextConfig.class})
public class ApplicationContextConfig2 {
    @Bean(name = {"message2"})
    public String message() {
        return "hello";
    }

测试方法

@Test
public void  importTest() {
    AnnotationConfigApplicationContext ctx = 
        new AnnotationConfigApplicationContext(ApplicationContextConfig2.class);
    Assert.assertEquals("hello", ctx.getBean("message"));
}

@ComponentScan

按照默认规则,它会以配置类所在的包作为基础包(basepackage)来扫描组件.

但是,如果你想扫描不同的包,那该怎么办呢?或者,如果你想扫描多个基础包,那又该怎么办呢?

有一个原因会促使我们明确地设置基础包,那就是我们想要将配置类
放在单独的包中,使其与其他的应用代码区分开来。如果是这样的
话,那默认的基础包就不能满足要求了。

要满足这样的需求其实也完全没有问题!为了指定不同的基础包,你
所需要做的就是在@ComponentScan的value属性中指明包的名称:

Paste_Image.png
如果你想更加清晰地表明你所设置的是基础包,那么你可以通过
basePackages属性进行配置:

Paste_Image.png

可能你已经注意到了basePackages属性使用的是复数形式。如果
你揣测这是不是意味着可以设置多个基础包,那么恭喜你猜对了。如
果想要这么做的话,只需要将basePackages属性设置为要扫描包
的一个数组即可:

Paste_Image.png
在上面的例子中,所设置的基础包是以String类型表示的。我认为
这是可以的,但这种方法是类型不安全(not type-safe)的。如果你重
构代码的话,那么所指定的基础包可能就会出现错误了。
除了将包设置为简单的String类型之外,@ComponentScan还提供了
另外一种方法,那就是将其指定为包中所包含的类或接口:

![Uploading Paste_Image_603936.png …]
可以看到,basePackages属性被替换成了basePackageClasses。同时,我们不是再使用String类型的名称来指定包,为basePackageClasses属性所设置的数组中包含了类。这些类所在的包将会作为组件扫描的基础包。
尽管在样例中,我为basePackageClasses设置的是组件类,但是你可以考虑在包中创建一个用来进行扫描的空标记接口(markerinterface)。通过标记接口的方式,你依然能够保持对重构友好的接口引用,但是可以避免引用任何实际的应用程序代码

结合基于Java和基于XML方式的配置

基于Java方式的配置方式不是为了完全替代基于XML方式的配置,两者可以结合使用,因此可以有两种结合使用方式:
 在基于Java方式的配置类中引入基于XML方式的配置文件;
 在基于XML方式的配置文件中中引入基于Java方式的配置。

1. 在基于Java方式的配置类中引入基于XML方式的配置文件

在@Configuration注解的配置类上通过@ImportResource注解引入基于XML方式的配置文件,示例如下所示:
1、定义基于XML方式的配置文件(chapter12/configuration/importResource.xml):

<bean id="message3" class="java.lang.String">
    <constructor-arg index="0" value="test"></constructor-arg>
</bean>

2、修改基于Java方式的配置类ApplicationContextConfig,添加如下注解:

@Configuration("ctxConfig") //1、使用@Configuration注解配置类
@ImportResource("classpath:chapter12/configuration/importResource.xml")
public class ApplicationContextConfig {
……
}

使用@ImportResource引入基于XML方式的配置文件,如果有多个请使用@ImportResource({“config1.xml”, “config2.xml”})方式指定多个配置文件

在基于XML方式的配置文件中中引入基于Java方式的配置:

直接在XML配置文件中声明使用@Configuration注解的配置类即可,示例如下所示:
1、定义基于Java方式的使用@Configuration注解的配置类在此我们使用ApplicationContextConfig.java。
2、定义基于XML方式的配置文件(chapter12/configuration/xml-config.xml):

<context:annotation-config/>
<bean id="ctxConfig"
 class="cn.javass.spring.chapter12.configuration.ApplicationContextConfig"/>

 :用于开启对注解驱动支持,详见【12.2 注解实现Bean依赖注入】;
 :直接将使用@Configuration注解的配置类在配置文件中进行Bean定义即可

基于Java方式的容器实例化

一、对于只有一个@Configuration注解的配置类,可以使用如下方式初始化容器:

AnnotationConfigApplicationContext ctx = 
new AnnotationConfigApplicationContext(ApplicationContextConfig.class);

二、对于有多个@Configuration注解的配置类,可以使用如下方式初始化容器:

AnnotationConfigApplicationContext ctx1 = 
new AnnotationConfigApplicationContext(
ApplicationContextConfig.class, ApplicationContextConfig2.class);

三、对于【12.3 注解实现Bean定义】中通过扫描类路径中的特殊注解类来自动注册Bean定义,可以使用如下方式来实现

public void testComponentScan() {
AnnotationConfigApplicationContext ctx = 
new AnnotationConfigApplicationContext();
    ctx.scan("cn.javass.chapter12.confiuration");
    ctx.refresh();
    Assert.assertEquals("hello", ctx.getBean("message"));
}

等价于

<context:component-scan base-package="cn.javass.chapter12.confiuration"/>

四、在web环境中使用基于Java方式的配置,通过修改通用配置实现

1、修改通用配置中的Web应用上下文实现,在此需要使用AnnotationConfigWebApplicationContext:

<context-param>
<param-name>contextClass</param-name>      
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>

2、指定加载配置类,类似于指定加载文件位置,在基于Java方式中需要指定需要加载的配置类:

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
cn.javass.spring.chapter12.configuration.ApplicationContextConfig,
cn.javass.spring.chapter12.configuration.ApplicationContextConfig2
    </param-value>

 contextConfigLocation:除了可以指定配置类,还可以指定“扫描的类路径”,其加载步骤如下:
1、首先验证指定的配置是否是类,如果是则通过注册配置类来完成Bean定义加载,即如通过ctx.register(ApplicationContextConfig.class)加载定义;
2、如果指定的配置不是类,则通过扫描类路径方式加载注解Bean定义,即将通过ctx.scan(“cn.javass.chapter12.confiuration”)加载Bean定义。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值