@Configuration和@Component注册的@Bean

0. 区别

直接讲一下区别:
在配置类的方法间调用时,如果类时@component标注的,每次调用获取的都是新的实体;而如果是@configuration标注的话,每次调用返回的是同一个实体Bean。其他方面都是相同,可以无差别使用(装配注入等)。看一下代码可能更加清晰一点:

在这里插入图片描述
在这里插入图片描述

哪是什么原因造成的呢?不卖关子,是因为@Configuration标注下的@Bean调用函数使用都是代理对象,获取的都是从IOC容器里获取的bean,因此都是同一个。而@Component标注下的@Bean下只是普通的函数方法调用。下面来看一下@configuration注册@Bean生成代理的过程。

1. @Bean的注册原理和过程

其实再看@Enable***注解的实现原理的时候有提到。是在ConfigurationClassPostProcessor类中解析的:

在这里插入图片描述

看一下注册的地方:

在这里插入图片描述

然后是生成代理的地方和生成代理拦截方法:

public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
        Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<String, AbstractBeanDefinition>();
        for (String beanName : beanFactory.getBeanDefinitionNames()) {
            BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
            if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {  // 只有带@Configuration注解的类才会被代理
                if (!(beanDef instanceof AbstractBeanDefinition)) {
                    throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
                            beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
                }
                else if (logger.isWarnEnabled() && beanFactory.containsSingleton(beanName)) {
                    logger.warn("Cannot enhance @Configuration bean definition '" + beanName +
                            "' since its singleton instance has been created too early. The typical cause " +
                            "is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
                            "return type: Consider declaring such methods as 'static'.");
                }
                configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
            }
        }
        if (configBeanDefs.isEmpty()) {
            // nothing to enhance -> return immediately
            return;
        }
        ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer(); // 增强类,内有增强方法..(省略代码)
    }

可以看到只有被@Configuration注解标识的类才会被增强。看一下增强类和设置的callBack。
在这里插入图片描述
在这里插入图片描述

BeanMethodInterceptor会根据方法名去IOC找到Bean并返回,具体代码就不贴了。

2. CGLIB内部方法调用:

在这里插入图片描述

看一下getObjectMethod字节码:

 0 getstatic #2 <java/lang/System.out>
 3 ldc #6 <getObjectMethod>
 5 invokevirtual #4 <java/io/PrintStream.println>
 8 aload_0
 9 invokevirtual #7 <com/study/h/config/testConfigurationBean/enhancer/EnhancerModel.getObject>
12 areturn

可以看到getObjectMethod方法中的getObject()方法仍旧会通过代理对象调用getObject方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值