第4章-Spring基于Java配置的容器

Spring 容器的元数据可以基于 Java 代码配置,它像 XML 配置一样不侵入源代码,同时也支持注解配置。

你可以在项目中任意选择哪种配置方式,或者多种方式共存。

一、Bean 管理

1. 元数据

基于 Java 配置 Bean,定义一个类并使用 @Configuration 注解作为配置类,在类中的方法上使用 @Bean 注解,就会注册一个以方法返回值为实例的 Bean。

@Configuration
public class AppConfig {

    @Bean
    public BeanExample beanExample() {
        return new BeanExample();
    }

    @Bean
    public BeanProvider beanProvider() {
        return new BeanProvider();
    }
}

默认使用方法名称作为 Bean 名称,也可以通过注解的 valuename 属性来指定。

使用 AnnotationConfigApplicationContext 来实例化容器。

public static void main(String[] args) {
    ApplicationContext applicationContext =
        new AnnotationConfigApplicationContext(AppConfig.class);
    BeanExample beanExample = (BeanExample) applicationContext.getBean("beanExample");
}

Bean 作用域

使用 @Scope 注解来指定 Bean 的作用域。

@Bean
@Scope("singleton")
public BeanExample beanExample() {
    return new BeanExample();
}

作用域类型参阅《Spring基于XML配置的容器

2. Full 模式和 Lite 模式

一般情况下,@Bean 用于 @Configuration 注解的类下,这种方式为 Full 模式。

@Bean 用于其他注解(如 @Component)的类下,或者为任何一个 Bean 内部的方法,这种情况为 Lite 模式。

// Full
@Configuration
public class AppConfig {

    @Bean
    public BeanExample beanExample() {
        return new BeanExample();
    }
}

// Lite
@Component
public class AppConfig {

    @Bean
    public BeanExample beanExample() {
        return new BeanExample();
    }
}

Full 模式会生成 CGLIB 代理类,可以通过方法调用来依赖其它 Bean。

Lite 模式则不生成,可以提高运行性能,降低启动时间。

为了避免方法调用注入依赖的 Bug,推荐在业务中使用 Full 模式,在组件工具封装中使用 Lite 模式。

Spring 5.2.x 版本后,@Configuration 可以指定属性 proxyBeanMethods 为 false,来禁用 CGLIB 进入 Lite 模式。

3. 组合配置

为了实现模块化配置,可以定义多个配置类,在配置类中使用 @Import 注解来导入其他配置类。

在实例化容器的时候,只需要指定 AppConfig 类,不需要指定所有配置类。

@Configuration
public class OtherConfig {

    @Bean
    public BeanProvider beanProvider() {
        return new BeanProvider();
    }
}

@Configuration
@Import(OtherConfig.class)
public class AppConfig {

    @Bean
    public BeanExample beanExample(BeanProvider beanProvider) {
        BeanExample beanExample = new BeanExample();
        beanExample.setBeanProvider(beanProvider);
        return beanExample;
    }
}

4. 扫描类路径配置

使用 @ComponentScan 来配置扫描的包路径,支持基于注解配置。

@Configuration
@ComponentScan(basePackages = "cn.codeartist.spring.bean.java")
public class AppConfig {

}

参阅上一篇《Spring基于注解配置的容器

二、依赖管理

配置类同样是一个 Bean,也支持字段注入、构造器注入和 Setter 方法注入依赖。

@Configuration
public class AppConfig {

    @Autowired
    private BeanProvider beanProvider;

    @Bean
    public BeanExample beanExample() {
        BeanExample beanExample = new BeanExample();
        beanExample.setBeanProvider(beanProvider);
        return beanExample;
    }
}

1. 依赖注入

1.1 参数注入

依赖的 Bean 可以通过方法参数注入。

@Bean
public BeanExample beanExample(BeanProvider beanProvider) {
    BeanExample beanExample = new BeanExample();
    beanExample.setBeanProvider(beanProvider);
    return beanExample;
}

1.2 方法注入

在同一个配置类中,可以直接调用方法来依赖其它 Bean,该方式只在生成 CBLIB 代理类的 Full 模式下才生效。

@Configuration
public class AppConfig {

    @Bean
    public BeanExample beanExample() {
        BeanExample beanExample = new BeanExample();
        beanExample.setBeanProvider(beanProvider());
        return beanExample;
    }

    @Bean
    public BeanProvider beanProvider() {
        return new BeanProvider();
    }
}

2. 依赖关系

使用 @DependsOn 注解指定依赖关系。

@Bean
@DependsOn("beanProvider")
public BeanExample beanExample() {
    return new BeanExample();
}

3. 懒加载

使用 @Lazy 注解配置懒加载。

@Lazy
@Bean
public BeanProvider beanProvider() {
    return new BeanProvider();
}

懒加载 Bean 在注入的地方也要加上 @Lazy 注解,或者使用 ApplicationContext.getBean() 方法获取 Bean,才能使懒加载生效。

@Bean
public BeanExample beanExample(@Lazy BeanProvider beanProvider) {
    BeanExample beanExample = new BeanExample();
    beanExample.setBeanProvider(beanProvider);
    return beanExample;
}

三、附录

1. 常用注解

注解 描述
@Configuration 指定 Bean 的配置类
@Bean 配置 Bean 元数据,作用于方法上,方法返回值作为 Bean 实例
@Scope 指定 Bean 的作用域
@Import 导入其他配置类
@DependsOn 指定 Bean 的依赖关系
@Lazy 配置懒加载

2. 示例代码

Gitee 仓库:

https://gitee.com/code_artist/spring

项目模块:

spring-ioc

示例路径:

cn.codeartist.spring.bean.java

posted @ 2022-11-27 15:57  码匠_CodeArtist  阅读(44)  评论(0编辑  收藏  举报