@Configuration详解

2年前 (2022) 程序员胖胖胖虎阿
222 0 0

@Configuration详解,功能:将想要的组件添加到容器中

首先,需要准备三个文件:

ps:完整代码片在文章最后,建议看完教程。
1.主程序类:
@Configuration详解
2.宠物类
@Configuration详解

3.用户类
@Configuration详解

对比以前原生spring添加组件的区别
如果是以前的原生spring,想要将组件添加到容器中
1.需要在resources目录下创建一个xml配置文件
2.创建bean标签
@Configuration详解

现在的Spring Boot已经不需要向以前一样了,有一个注解@Configuration(翻译:配置)可以供使用
1.创建一个类。
2.使用注解@Configuration,告诉Spring Boot这是一个配置类。
@Configuration详解

这个时候在类里边不能写bean标签了需要使用@bean注解,想要构建出user和pet对象需要自己将它创造出来。
@bean:给容器中添加组件,以方法名作为组件的id。返回类型为组件类型,返回的值,就是组件在容器中的实例
@Configuration详解

怎么验证创建这俩组件成功了呢?
首先来到主程序
@Configuration详解

运行主程序就能查到刚刚创建好的组件:
@Configuration详解

当然,如果不喜欢这个原本的名字是可以换的
@Configuration详解

给容器中注册的组件默认是单实例的。
就是说无论我们从容器中获取多少次,它们都是一样的
@Configuration详解

可以看到,返回的都是true,也就说明都是相等的 。
所以:配置类里面使用@Bean标注在方法上给容器注册组件,默认是单实例的。
同时还有一点,被@Configuration标注的类本身也是一个组件
可以从容器中取这个类来验证一下。
@Configuration详解

同时,在Spring Boot 5.2之后的@Configuration注解多了一个属性proxyBeanMethods,默认为true(翻译:代理bean的方法)
@Configuration详解

顾名思义,既然默认为true了,也就是默认代理。
代理就会保持组件的单实例。
也就是说,虽然写的Myconfig是在容器中注册组件用的,但是在注册组件之前会在容器中查找有没有该组件。如果有,则取该组件用于保证单实例,如果没有再注册一个新的组件。
这里可以调用两次注册组件的方法来确认是否使用了代理:
@Configuration详解

虽然是调用了两次,可它们两个是相等的,也就是说使用了代理,取的都是同一个值。
如果将@Configuration(proxyBeanMethods = true)改为false
@Configuration详解

再次运行就会发现这次取的不是代理对象,也就是每一个方法都新注册了一个组件,所以两个不相等。
因为改为false后久不会再保存代理对象了。
@Configuration详解

proxyBeanMethods:代理bean的方法
有两种模式:
1.Full:(proxyBeanMethods = true) //全模式
使用代理模式,保证组件的单实例,启动不如false快,但是重复利用率高,适用于会重复使用组件的场景。
2.lite:(proxyBeanMethods = false) //轻量级
不是用代理模式,不用保证组件的单实例,启动最快。单每次调用组件都会重新创建一个新的组件,组件可重复使用率低。适用于需要组件但不会重复使用的场景
总结:用于解决组件依赖
可有验证方法:
1.在User类加入Pet类,同时增加get和set方法
@Configuration详解

2.在Myconfig类使用user01调用pet01
@Configuration详解

3.在主程序中获取user01和pet01组件,并将user01组件中的Pet类和组件pet01组件进行对比。
@Configuration详解

4.对比结果:
当proxyBeanMethods = true时,两者是相等的,代表使用了代理模式没用重新创建pet01组件
@Configuration详解

当proxyBeanMethods = false时,两者对比不相等,表示重新创建了组件
@Configuration详解

最终程序代码片:
1.主程序类:


/**
 * 这是一个主程序类
 * @SpringBootApplication:表明这是一个SpringBoot应用
 */
@SpringBootApplication(scanBasePackages="com.shiyi")
public class MainApplication {

    public static void main(String[] args) {
        //1、返回我们ioc容器
        ConfigurableApplicationContext run =
                SpringApplication.run(MainApplication.class, args);

        //2、查看容器里面的组件
        String[] names = run.getBeanDefinitionNames();
        for(String name : names){
            System.out.println(name);//打印出所有的组件名称
        }

        //3、从容器中获取组件
//        Pet pet01 = run.getBean("德玛西亚~",Pet.class);
//
//        Pet pet02 = run.getBean("德玛西亚~",Pet.class);

//        System.out.println("是否相等"+(pet01 == pet02));
//        System.out.println("是否相同"+pet01.equals(pet02));

        Myconfig bean = run.getBean(Myconfig.class);
        System.out.println("配置类---"+bean);//进度08:15

        User user = bean.user01();
        User user1 = bean.user01();
        System.out.println("验证是否使用代理:"+(user == user1));

        User user01 = run.getBean("user01", User.class);
        Pet pet011 = run.getBean("pet01", Pet.class);

        System.out.println("用户的宠物:"+(user01.getPet() == pet011));


    }

}

2.配置类


/**
 * 1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
 * 2、配置类本身也是组件
 * 3、proxyBeanMethods:代理bean的方法
 *      Full:(proxyBeanMethods = true)  //全模式
 *      lite:(proxyBeanMethods = false) //轻量级
 *      用于解决组件依赖
 */
@Configuration(proxyBeanMethods = true) //告诉springboot这是一个配置类 == 配置文件
public class Myconfig {

    @Bean//给容器中添加组件,以方法名作为组件的id。
    // 返回类型为组件类型,返回的值,就是组件在容器中的实例
    public User user01(){
        User wangcai = new User("wangcai",23);
        //user组件依赖了pet组件
        wangcai.setPet(pet01());
        return wangcai;
    }

    @Bean
    public Pet pet01(){
        return new Pet("旺财");
    }

}

3.User类


/**
 * 用户
 */
public class User {

    private String name;

    private Integer age;

    private Pet pet;

    public User(){

    }

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public Pet getPet() {
        return pet;
    }

    public void setPet(Pet pet) {
        this.pet = pet;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

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

4.Pet类


/**
 * 宠物
 */
public class Pet {

    private String name;

    public Pet() {
    }

    public Pet(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

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

版权声明:程序员胖胖胖虎阿 发表于 2022年10月2日 下午8:24。
转载请注明:@Configuration详解 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...