@Configuration源码分析

@Data
public class Kc {

    private String name;
}
@Data
public class User {

    private int age;

    private Kc kc;

}
/**
 *
 * 配置类 注册到容器中,默认单实例
 * 配置类 本身也是组件
 * 相当于以前的bean.xml
 * @param
 * @return
 * @throws Exception
 */
@Configuration
public class TestConfig {


    @Bean
    public User user1(){
        User user=new User();
        user.setAge(111);
        user.setKc(kc());
        return user;
    }

    @Bean("kc1")
    public Kc kc(){
        Kc kc=new Kc();
        kc.setName("aaa");
        return kc;
    }
}
@SpringBootApplication
public class ClientApplication {


    public static void main(String[] args) {
        //返回我们ioc容器
        ConfigurableApplicationContext run = SpringApplication.run(ClientApplication.class, args);
        //查看容器里面的组件
        String[] beanDefinitionNames = run.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
        System.out.println("===========================");
        //从容器中获取对象
        User u1 = run.getBean(User.class);
        User u2=run.getBean("user1",User.class);
        System.out.println(u1.getClass());
        System.out.println(u2.getClass());
        System.out.println(u1==u2);

        System.out.println("------------------------------");
        Kc kc=run.getBean("kc1",Kc.class);
        System.out.println(kc.getClass());

        System.out.println("------------------------------");
        TestConfig testConfig=run.getBean(TestConfig.class);
        System.out.println(testConfig);
    }

}

当我们使用了@Configuration,那么就会注册到容器中

当使用@Bean("kc1")那么会把容器名字改成kc1

当我们直接使用@Bean,对应的user1()方法名,对应容器里面的名字就是user1

我们的注册到容器的对象,默认是单例模式的,可以看到2个user都一样

并且是cglib动态代理的

默认proxyBeanMethods = true

proxyBeanMethods就是代理bean方法

如果设置为true,springboot启动的时候,都会检查这个组件在容器中是否存在,如果有保持组件单例

并且也是重量级模式(full),bean方法注册的组件都会去容器找组件

proxyBeanMethods = true 并且设置代理bean方法设置为true,组件依赖也是true

就是User里面使用了kc,和KC这个对象一样,所以是组件依赖

proxyBeanMethods = false 当代理bean方法设置为false的时候

TestConfig就不在是代理对象了,而是类本身

springboot在启动的时候,会很快,不会在容器中检查这些方法是否存在

在容器中也不会保存代理对象

并且也解决了组件依赖,就是User里面的kc和Kc类的对象,不一样了

也就是我们的Lite,轻量级模式

使用@Import({User.class}),也可以吧User注册到容器当中

前提必须是配合@Configuration一起使用

把之前的user1方法注释掉

启动类改成下面的代码

 public static void main(String[] args) {
        long start =System.currentTimeMillis();
        //返回我们ioc容器
        ConfigurableApplicationContext run = SpringApplication.run(ClientApplication.class, args);
        //查看容器里面的组件
        String[] beanDefinitionNames = run.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
        System.out.println("===========================");
        //从容器中获取对象
        User u1 = run.getBean(User.class);
        System.out.println(u1);

        System.out.println("------User对应的容器数组---------");
        String[] beanNamesForType = run.getBeanNamesForType(User.class);
        for (String s : beanNamesForType) {
            System.out.println(s);
        }
    }

可以看到使用@Import注解,类里面的输入没有赋值,并且在容器里面的名字是类全路径

而我们使用@Bean的注解的时候,都是使用的方法名字在容器中

在来看下@Conditional

条件装配:当满足了某些条件,才会注入到容器中

可以看到有这么多的条件类

我们先把kc1对应的bean注释掉

可以看到kc1不存在容器中

我们在@Bean方法上面加@ConditionalOnBean这个注解name = "kc1"

表示如果没有bean的名字叫kc1的 那么和他有依赖关联的,都不会在容器中注册

可以发现,我已经加了@ConditionalOnBean注解,并且kc1已经注册了

为啥user1还不显示呢?

是顺序问题,把kc1放入user1上面,因为user1的容器注册的时候,kc1还没有注册,所以这里是false

我们把顺序切换后,就打印true了

当我们设置一个不存在容器的kc2,那么打印user1这个容器就是false,不会注册到容器中

我们在看下@ConditionalOnMissingBean(name = "kc1")

如果容器中不存在kc1,那么就会注册到容器中

可以看到,我们的kc1是存在容器中的,所以这里打印的user1就是false,没被注册到容器中

我们在设置kc2不存在容器中,所以都打印true

在springboot中,我们是不使用bean.xml这种方式的

在启动类获取容器的时候发现没有

但是我们可以使用@ImportResource({"classpath:bean.xml"}) 这个注解导入一份资源

把bean.xml导入进来让他注册到容器当中,现在打印就是true了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值