spring小结(4)--invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

本文深入解析Spring中的BeanFactoryPostProcessor接口的回调过程,特别是ConfigurationClassPostProcessor如何利用CGLIB为配置类创建代理。通过示例展示了配置类加与不加@Configration注解时的区别,以及CGLIB代理如何避免重复创建bean实例,同时探讨了spring的拦截器过滤器CALLBACK_FILTER和不同拦截策略。
摘要由CSDN通过智能技术生成

承接上一小节,

介绍invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

//回调实现BeanFactoryPostProcessor的实现类,目前默认加载的processor有ConfigurationClassPostProcessor,

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
      PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
  

。。。。。。。。。

其中;

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
  

。。。。。。。。。。。。。

那么查看

ConfigurationClassPostProcessor关于BeanFactoryPostProcessor 的实现
/**
 * Prepare the Configuration classes for servicing bean requests at runtime
 * by replacing them with CGLIB-enhanced subclasses.
 */
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   int factoryId = System.identityHashCode(beanFactory);
   if (this.factoriesPostProcessed.contains(factoryId)) {
      throw new IllegalStateException(
            "postProcessBeanFactory already called on this post-processor against " + beanFactory);
   }
   this.factoriesPostProcessed.add(factoryId);
   if (!this.registriesPostProcessed.contains(factoryId)) {
      // BeanDefinitionRegistryPostProcessor hook apparently not supported...
      // Simply call processConfigurationClasses lazily at this point then.
      processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
   }

   enhanceConfigurationClasses(beanFactory);
   beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

其中调用了cglib为产生Config类产生代理,如果配置类没有加@Configration,下面会直接return, 加了会继续执行

/**
 * Post-processes a BeanFactory in search of Configuration class BeanDefinitions;
 * any candidates are then enhanced by a {@link ConfigurationClassEnhancer}.
 * Candidate status is determined by BeanDefinition attribute metadata.
 * @see ConfigurationClassEnhancer
 */
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
   Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
   for (String beanName : beanFactory.getBeanDefinitionNames()) {
      BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
      if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) { //之前说过有@Configuration,是Full标志,只加@ComponentScan而无@Configuration,是Lite标志,现在那些标志在这里用到了
         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();
   for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
      AbstractBeanDefinition beanDef = entry.getValue();
      // If a @Configuration class gets proxied, always proxy the target class
      beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
      try {
         // Set enhanced subclass of the user-specified bean class
         Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
         if (configClass != null) {
            Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
            if (configClass != enhancedClass) {
               if (logger.isDebugEnabled()) {
                  logger.debug(String.format("Replacing bean definition '%s' existing class '%s' with " +
                        "enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
               }
               beanDef.setBeanClass(enhancedClass);
            }

测试下:

加了@config

@Configuration
@ComponentScan("com.lmq.BaseService")
//@Import(MyImportBeanDefinitionRegistrar.class)
@Import(MyImportSelector.class)
public class AppConfig {


}

输出如下:此时appconfig是个cglib增强的代理类

没加,先注释掉
//@Configuration
@ComponentScan("com.lmq.BaseService")
//@Import(MyImportBeanDefinitionRegistrar.class)
@Import(MyImportSelector.class)
public class AppConfig {


}

输出  //此时appconfig是个普通类

 

为了说明cglib代理作用,这里

举个例子

package com.lmq.BaseService;

public class lmqDao {


    public lmqDao()
    {
        System.out.println("lmqdao1-init");
    }
}

无注解

同理public class lmqDao1 {

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值