IoC容器篇(十二)——基于Java的容器配置(一)

目录

基于Java的容器配置

1.基本概念:@Bean与@Configuration

2.使用AnnotationConfigApplicationContext初始化Spring容器

3.使用@Bean注解

翻译源:Spring官方文档


基于Java的容器配置

1.基本概念:@Bean与@Configuration

Spring的基于java的配置所支持的核心工件为@Configuration类与@Bean方法。

@Bean注解用于指定一个方法,此方法用于实例化、配置和初始化一个由Spring容器管理的对象。即@Bean注解与xml配置中的<bean>元素作用等价。

@Bean可以与任意@Component使用,不过,常常与@Configuration同时使用。

@Configuration类的主要目的是作为一个bean定义的源。

@Configuration允许内部bean依赖通过简单调用定义在当前类下的@Bean方法进行定义。

 

@Configuration
public class AppConfig {
    
    @Bean
    public Foo foo() {
        return new FooImpl();
    }
}
<beans>
    <bean id="foo" class="examples.FooImpl" />
</beans>

note:以上两种配置等价。

 

当@Bean方法没有声明在@Configuration类中时,这些方法被认为是在lite模式下运行。即,@Bean方法可以被看作是提供了一种通用的工厂方法机制,没有其他特别的运行时语义。

"lite"@Bean方法不能声明内部bean依赖。由于没有CGLIB子类在运行时生成,所以,当进行类设计时,没有任何限制。(eg:class可以设置为final。)

"full"模式被使用时,交叉方法引用会被重定向到容器生命周期管理。这将会阻止相同@Bean方法被通过常规java调用方式意外调用,从而帮助降低难以发现的bug。

 

2.使用AnnotationConfigApplicationContext初始化Spring容器

AnnotationConfigApplicationContext除了能够接收@Configuration类作为输入,还可以接受简单@Component类以及被JSR-330注解的类。

当@Configuration类被作为输入提供时,@Configuration类本身也会作为bean定义被注册,并且所有声明其中的@Bean方法都会被作为bean定义注册。

当@Component与JSR-330类被提供时,它们会作为bean定义被注册,DI元数据(@Autowired或@Inject)会在必要的时候被使用。

 

简单构造

public static void main(String[] args) {

    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
}

note:将@Configuration类作为源输入构建的ApplicationContext中。

 

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(Example.class, Foo.class);
}

note:将多个@Component或JSR-300的注解类作为输入,构建ApplicationContext。

note:这些输入的类使用依赖注入标签。(eg:@Autowired等)

 

通过编程方式register(Class<?>...)构建容器

public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    ctx.register(AppConfig.class, OtherConfig.class);
    ctx.register(AdditionalConfig.class);
    ctx.refresh();

}

 

启用组件扫描

@Configuration
@ComponentScan(basePackages = "com.acme")
public class AppConfig  {
    ...
}

note:使用@ComponentScan注解开启组建扫描。

 

public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    ctx.scan("com.acme");
    ctx.refresh();
}

note:使用AnnotationConfigApplicationContext提供的scan(String...)方法启用组件扫描功能。

ps:@Configuration注解由元注解@Component构成,所以,自动扫描会将@Configuration类作为组建扫描的候选,将其作为容器中的beam定义进行注册。

 

在web应用中支持AnnotationConfigWebApplicationContext

<web-app>
    <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
        instead of the default XmlWebApplicationContext -->
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.support.AnnotationConfigWebApplicationContext
        </param-value>
    </context-param>

    <!-- Configuration locations must consist of one or more comma- or space-delimited
        fully-qualified @Configuration classes. Fully-qualified packages may also be
        specified for component-scanning -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.acme.AppConfig</param-value>
    </context-param>

    <!-- Bootstrap the root application context as usual using ContextLoaderListener -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Declare a Spring MVC DispatcherServlet as usual -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
            instead of the default XmlWebApplicationContext -->
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>
                org.springframework.web.context.support.AnnotationConfigWebApplicationContext
            </param-value>
        </init-param>
        <!-- Again, config locations must consist of one or more comma- or space-delimited
            and fully-qualified @Configuration classes -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>com.acme.web.MvcConfig</param-value>
        </init-param>
    </servlet>

    <!-- map all requests for /app/* to the dispatcher servlet -->
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>
</web-app>

note:web.xml配置。

 

3.使用@Bean注解

@Bean时方法层次注解,与xml的<bean>元素作用类似。

 

声明一个bean

@Configuration
public class AppConfig {

    @Bean
    public FooImpl foo() {
        return new FooImpl();
    }
}

note:声明一个名称为foo,类型为FooImpl的bean。

ps:bean的类型由方法返回值指定。

ps:默认情况下,bean的名称为方法名。

ps:可以将返回值设置为一个接口或base类。

ps:将返回值设置为接口,这会限制对特定接口的类型预测的可见性,即只有当被影响的单例bean实例化时,实际类型才会被容器得知。

ps:非怠惰bean根据声明顺序进行实例化。所以,其他组件试图通过未声明类型进行匹配的时机,将会决定类型匹配的结果。

ps:如果坚持通过已声明的服务接口来引用类型,@Bean返回类型可以安全地参与设计决策。

ps:对于实现多个接口的组件,通过声明最特殊的返回类型可能是安全的。

 

bean依赖

@Bean方法可以通过任意数量的参数来描述构建bean所必需的依赖。

@Configuration
public class AppConfig {

    @Bean
    public Example example(Foo foo) {
        return new Example(foo);    
    }
}

note:这种方式注入与基于构造器的注入方式等价。通过参数类型进行bean注入。

 

接收生命周期回调

@Bean支持指定任意initialization回调方法与destruction回调方法,类似于xml的bean元素的init-method属性与destroy-method属性。

public class Foo {

    public void init() {
        // initialization logic
    }
}

public class Bar {

    public void cleanup() {
        // destruction logic
    }
}

@Configuration
public class AppConfig {

    @Bean(initMethod = "init")
    public Foo foo() {
        return new Foo();
    }

    @Bean(destroyMethod = "cleanup")
    public Bar bar() {
        return new Bar();
    }
}

 

默认情况下,由java配置定义的beans会有默认的公共close方法与shutdown方法,这些方法默认作为destruction回调。

可以使用@Bean(destroyMethod="")阻止默认destruction回调执行。

 

指定bean范围

@Configuration
public class MyConfiguration {

    @Bean
    @Scope("prototype")
    public Encryptor encryptor() {
        // ...
    }
}

Spring提供了一种方便的方法与范围限定的代理一起执行。

配置通过java中的beans的@Scope注解,提供一个proxyMode属性。

默认情况下,值为ScopeProxyMode.NO(无代理),可以手动指定ScopedProxyMode.TARGET_CLASS或ScopedProxyMode.INTERFACES。

 

定制bean名称

@Configuration
public class AppConfig{

    @Bean(name="myFoo")
    public Foo foo() {
        return new Foo();
    }
}

note:将@Bean默认定义的bean名称(方法名),重载为myFoo。

 

bean别名

@Configuration
public class AppConfig {

    @Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" })
    public DataSource dataSource() {
        // instantiate, configure and return DataSource bean...
    }
}

 

bean描述

@Configuration
public class AppConfig {

    @Bean
    @Description("Provides a basic example of a bean")
    public Foo foo() {
        return new Foo();
    }
}

 

 


翻译源:Spring官方文档

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值