Spring Boot-@Configuration注解
阅读原文时间:2023年07月09日阅读:1

@Configuration
public class MyConfigFile {

    @Bean
    public HelloService helloService(){
        return new HelloService();
    }
}

使用@Bean添加组件

@SpringBootTest
class SpringBoot02ApplicationTests {

    @Autowired
    ApplicationContext ioc;

    @Test
    public void testHelloService(){
        boolean helloService = ioc.containsBean("helloService");
        System.out.println(helloService);
    }

}

测试:true


@Configuration注解进阶内容

1.创建一个User实体类

package com.hao.springbooton.bean;

/**
 * @author:抱着鱼睡觉的喵喵
 * @date:2020/12/22
 * @description:
 */
public class User {

    private String username;

    private String password;

    private int age;

    public User() {
    }

    public User(String username, String password, int age) {
        this.username = username;
        this.password = password;
        this.age = age;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }
}

2.编写一个MyConfig的配置类

/**
 * @author:抱着鱼睡觉的喵喵
 * @date:2020/12/22
 * @description:配置类
 */
@Configuration
public class MyConfig {

    @Bean("hao")
    public User user(){
        return new User("tom","123",20);
    }

}

3.在主配置文件从容器中获取user

@SpringBootApplication
public class SpringBootOnApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext run=SpringApplication.run(SpringBootOnApplication.class, args);
        //判断从容器中获取的是否是单实例
        User tom = run.getBean("hao", User.class);
        User tom1 = run.getBean("hao",User.class);
        System.out.println(tom==tom1);
        //通过配置类调用查看两次调用的结果
        MyConfig co = run.getBean(MyConfig.class);
        System.out.println(co);
        User user = co.user();
        User user1 = co.user();
        System.out.println(user==user1);
    }
}

结果:

我们编写的MyConfig配置类也是一个组件,配置类中注入的对象也是组件,我们发现通过配置类调用完这个user方法,两者是同一个user对象;所以无论是从另外一个组件中获取(比如MyConfig是一个组件)组件(对象),Spring都会从容器中进行查看是否存在该组件(从一个组件中调用另外一个组件也叫做组件依赖,具体看下面)
我们可以查看@Configuration注解源码

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";

    boolean proxyBeanMethods() default true;
}

接下来我们引进组件依赖

编写Admin类

public class Admin {
    private String name;
    private String img;

    public Admin() {
    }

    public Admin(String name, String img) {
        this.name = name;
        this.img = img;
    }

    @Override
    public String toString() {
        return "admin{" +
                "name='" + name + '\'' +
                ", img='" + img + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

修改User类,增加Admin属性

public class User {

    private String username;

    private String password;

    private int age;

    private Admin admin;

    public Admin getAdmin() {
        return admin;
    }

    public void setAdmin(Admin admin) {
        this.admin = admin;
    }

    public User() {
    }

    public User(String username, String password, int age) {
        this.username = username;
        this.password = password;
        this.age = age;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                ", admin=" + admin +
                '}';
    }
}

MyConfig的修改(相关说明已在注释中表明)

/**
 * @author:抱着鱼睡觉的喵喵
 * @date:2020/12/22
 * @description:配置类
 */

/**
 * Spring 5提供了Full模式和Lite模式
 * 组件依赖:容器中一个组件调用另外一个组件的情况
 * Lite:容器中组件没有依赖的情况:使用Lite模式能使容器快速启动
 * Full:容器中的组件存在依赖的情况,使用Full模式,由于在一个组件中存在调用另外一个组件的情况,所以会查看该组件在容器中是否存在,当然也就降低了容器启动的速度
 */
@Configuration(proxyBeanMethods = true)
public class MyConfig {

    @Bean("hao")
    public User user(){
        User tom = new User("tom", "123", 20);
        //hao组件依赖了admin组件
        tom.setAdmin(admin());
        return tom;
    }

    @Bean("admin")
    public Admin admin(){
        return new Admin("jerry","@the");
    }
}



@SpringBootApplication
public class SpringBootOnApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext run=SpringApplication.run(SpringBootOnApplication.class, args);

        MyConfig co = run.getBean(MyConfig.class);
        User hao = run.getBean("hao", User.class);
        Admin admin = run.getBean("admin", Admin.class);
        System.out.println(hao.getAdmin()==admin);
    }

}

此时运行结果:true

此时我把MyConfig类中的注解改为@Configuration(proxyBeanMethods = false)

@Configuration(proxyBeanMethods = false)
public class MyConfig {

    @Bean("hao")
    public User user(){
        User tom = new User("tom", "123", 20);
        //hao组件依赖了admin组件
        tom.setAdmin(admin());
        return tom;
    }

    @Bean("admin")
    public Admin admin(){
        return new Admin("jerry","@the");
    }
}

继续测试
结果:false

这说明当proxyBeanMethods = false时,Spring帮我们执行了Lite模式;


总结:假设我在配置类中,注入了两个组件(A和B)到容器中,组件A调用了组件B
Lite(proxyBeanMethods =false)模式:程序运行时Spring不会检查B组件是否存在,即上面举的例子中调用之后直接new个对象。
Full(proxyBeanMethods =true)模式:程序运行时,当A调用B时,Spring会检查容器中是否存在B组件,如果存在就从容器中拿

Lite和Full适用于的情况:当配置类中没有出现组件依赖的情况,使用Lite模式可以提高容器的启动速度。当配置中出现组件依赖的时候,使用Full模式最合适。

===========================================================
@Import是向容器中导入组件,需要和@Configuration注解一块使用

@Import({User.class,Admin.class})
@Configuration(proxyBeanMethods = true)
public class MyConfig {
}