@Configuation 和@Component区别源码简单分析

@Configuation 这个注解相信大家都使用过,那么它和普通的@Component的派生注解有什么不同呢。

先贴出一个最后总结的流程图


@Configuration大体逻辑流程

我们先随便百度还是谷狗一些内容。都谈到了@Configuration中@Bean可以在类内部调用注入bean的方法而不会产生两个实例,会保证单例。那么来看看这个逻辑

@Configuration
// 默认boolean proxyBeanMethods() default true 即当前@Configuation注解下的类会被设置为代理类
public class YhrConfigTest {


    @Bean
// proxyBeanMethods -> true 会代理 @Bean注解的方法,保证只会真正调用一次,后面的调用会直接从 spring ioc中取
    public PulsarTest init() {
        return new PulsarTest();
    }

    @Bean
    public TestBean initService() {
  // 默认的proxyBeanMethods -> true  支持这种类内部的重复调用 @Bean注解的方法获取bean,而又保证单例,通过 cglib的动代来实现
        PulsarTest pulsarTest = init();
        return new TestBean(pulsarTest);
    }
}
这种使用方式被视为ConfigurationClassUtils#CONFIGURATION_CLASS_FULL 即full 模式,另一种为lite模式不存在动态代理对象,为直接的@Configuration注解下的bean,区别就是full模式由动代进行了一层拦截处理。现在很多源码和官方推荐使用lite模式,即可以看到很多 proxyBeanMethods=false的代码,如果不适用到代理提供的特性尽量使用lite模式

我们来看看@Configuration 代理实现的具体逻辑

先从代理方法入手
  1. 我们跟踪上述代码中的另一个@Bean中的init()方法

class ConfigurationClassEnhancer {
// 省略部分代码...
// 这里一看就是 生成 cglib动态代理的方法。传入目标configClass和classLoader,一会可以从这里debug看 spring启动时当前方法外部逻辑
    public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
        if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
            if (logger.isDebugEnabled()) {
                logger.debug(String.format("Ignoring request to enhance %s as it has " +
                        "already been enhanced. This usually indicates that more than one " +
                        "ConfigurationClassPostProcessor has been registered (e.g. via " +
                        "<context:annotation-config>). This is harmless, but you may " +
                        "want check your configuration and remove one CCPP if possible",
                        configClass.getName()));
            }
            return configClass;
        }
// 这里生成了 动态代理 class
        Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
        if (logger.isTraceEnabled()) {
            logger.trace(String.format("Successfully enhanced %s; enhanced class name is: %s",
                    configClass.getName(), enhancedClass.getName()));
        }
        return enhancedClass;
    }

    /**
     * Creates a new CGLIB {@link Enhancer} instance.
     */
    private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(configSuperClass);
// 标记 cglib动态代理子类 方便从接口维度管理
        enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
        enhancer.setUseFactory(false);
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
// 字节码生成策略
        enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
// 动态代理拦截后 cglib的回调
        enhancer.setCallbackFilter(CALLBACK_FILTER);
    //同上 动态代理 cglib的回调,可以设置多个回调拦截,通过返回下表来选择指定的拦截实现生成,当前类中包含一个 无拦截生成逻辑。
org.springframework.cglib.proxy.NoOp,都实现了org.springframework.cglib.proxy.CallBack接口,如果需要真正的拦截,需要再实现MethodInterceptor 接口和上述类同包。也可以看看这个实现类中spring做了哪些拦截逻辑,结合CallbackFilter#accept方法,当前filter都会选中通过accept指定的Callback
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
        return enhancer;
    }
// 使用 spring的 cglib封装创建 class对象
    private Class<?> createClass(Enhancer enhancer) {
        Class<?> subclass = enhancer.createClass();
        // Registering callbacks statically (as opposed to thread-local)
        // is critical for usage in an OSGi environment (SPR-5932)...
        Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
        return subclass;
    }
// config的动态代理类 接口标记
    public interface EnhancedConfiguration extends BeanFactoryAware {
    }
  //
    private interface ConditionalCallback extends Callback {
// cglig 回调拦截的适配方法。哪些方法会被适配到拦截
        boolean isMatch(Method candidateMethod);
    }

    private static class ConditionalCallbackFilter implements CallbackFilter {
            // cglib 回调拦截 列表 只有三种,在当前类的成员变量中
        private final Callback[] callbacks;
      // 拦截方法的class 对象
        private final Class<?>[] callbackTypes;
        public ConditionalCallbackFilter(Callback[] callbacks) {
            this.callbacks = callbacks;
            this.callbackTypes = new Class<?>[callbacks.length];
            for (int i = 0; i < callbacks.length; i++) {
                this.callbackTypes[i] = callbacks[i].getClass();
            }
        }
// 当前方法是让具体的每个方法选择 callBack具体哪个实现,因为Spring的cglib动态代理对象可以放入多个 CallBack拦截实现具体可以看org.springframework.cglib.proxy.Enhancer#emitMethods
        @Override
        public int accept(Method method) {
// 这里实际是当前动态代理对象,符合当前
            for (int i = 0; i < this.callbacks.length; i++) {
                Callback callback = this.callbacks[i];
                if (!(callback instanceof ConditionalCallback) || ((ConditionalCallback) callback).isMatch(method)) {
// 当前method适用于那种 CallBack拦截逻辑(可能利用NoOp类不进行拦截)
                    return i;
                }
            }
            throw new IllegalStateException("No callback available for method " + method.getName());
        }

        public Class<?>[] getCallbackTypes() {
            return this.callbackTypes;
        }
    }


    // 字节码生成策略,这个是spring提供的cglib实现的逻辑
    private static class BeanFactoryAwareGeneratorStrategy extends
            ClassLoaderAwareGeneratorStrategy {
  
        public BeanFactoryAwareGeneratorStrategy(@Nullable ClassLoader classLoader) {
            super(classLoader);
        }

        @Override
        protected ClassGenerator transform(ClassGenerator cg) throws Exception {
            ClassEmitterTransformer transformer = new ClassEmitterTransformer() {
                @Override
                public void end_class() {
                    declare_field(Constants.ACC_PUBLIC, BEAN_FACTORY_FIELD, Type.getType(BeanFactory.class), null);
                    super.end_class();
                }
            };
            return new TransformingClassGenerator(cg, transformer);
        }

    }


// 要拦截setBeanFactory方法的代理方法,因为所有bean都会自动进行BeanFactoryAware#setBeanFactory钩子的回调,这里是拦截这个回调。如果当前类实现了BeanFactoryAware接口则返回父类的原始调用,不使用当前代理调用
    private static class BeanFactoryAwareMethodInterceptor implements MethodInterceptor, ConditionalCallback {

        @Override
        @Nullable
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            Field field = ReflectionUtils.findField(obj.getClass(), BEAN_FACTORY_FIELD);
            Assert.state(field != null, "Unable to find generated BeanFactory field");
// 生成的代理类会通过这个setBeanFactory方法的代理进行BeanFactory注入,将代理类和正常的bean一样将其与beanFactory自动连接起来
            field.set(obj, args[0]);
            // Does the actual (non-CGLIB) superclass implement BeanFactoryAware?
            // If so, call its setBeanFactory() method. If not, just exit.
            if (BeanFactoryAware.class.isAssignableFrom(ClassUtils.getUserClass(obj.getClass().getSuperclass()))) {
                return proxy.invokeSuper(obj, args);
            }
            return null;
        }
// 适配器,当前方法是否会被代理。
        @Override
        public boolean isMatch(Method candidateMethod) {
            return isSetBeanFactory(candidateMethod);
        }
// 从这个适配可以看处只代理了setBeanFactory(BeanFactory beanFactory)并且只有一个参数的方法
        public static boolean isSetBeanFactory(Method candidateMethod) {
            return (candidateMethod.getName().equals("setBeanFactory") &&
                    candidateMethod.getParameterCount() == 1 &&
                    BeanFactory.class == candidateMethod.getParameterTypes()[0] &&
                    BeanFactoryAware.class.isAssignableFrom(candidateMethod.getDeclaringClass()));
        }
    }
// 要代理 @Bean注解的方法
    private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {


        @Override
        @Nullable
        public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
                    MethodProxy cglibMethodProxy) throws Throwable {
// 获取bean工厂
            ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
// 获取 @Bean方法指定的 bean名称
            String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
// 除了默认单例的 其他作用域的bean
            // Determine whether this bean is a scoped-proxy
            if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
                String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
                if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
                    beanName = scopedBeanName;
                }
            }

            // To handle the case of an inter-bean method reference, we must explicitly check the
            // container for already cached instances.

            // First, check to see if the requested bean is a FactoryBean. If so, create a subclass
            // proxy that intercepts calls to getObject() and returns any cached bean instance.
            // This ensures that the semantics of calling a FactoryBean from within @Bean methods
            // is the same as that of referring to a FactoryBean within XML. See SPR-6602.
//*********这里是重点!!!这里就是上面@Bean方法和当前@Configuration类中的方法复用了@Bean方法,会看如果已经在容器中含有了,不会再次初始化,前提是@Configuration使用默认,那么当前类就是一个cglib代理,如果不是代理不会进入当前方法拦截噢。
            if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
                    factoryContainsBean(beanFactory, beanName)) {
// 如果已经在容器中,并且不是新建中的中间状态会进入当前代码块
                Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
                if (factoryBean instanceof ScopedProxyFactoryBean) {
// 如果是除了默认的 单例模式的bean,其他作用域都不做处理,会进行多次初始化
                    // Scoped proxy factory beans are a special case and should not be further proxied
                }
                else {
                    // It is a candidate FactoryBean - go ahead with enhancement
// 直接返回 cglib动态代理bean
                    return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
                }
            }

            if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
//兼容 groovy可能出现的 动态bean加载,当前factory正在调用getBean实例化当前bean则需要调用原始bean中的方法实现
                // The factory is calling the bean method in order to instantiate and register the bean
                // (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
                // create the bean instance.
                if (logger.isInfoEnabled() &&
                        BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
                    logger.info(String.format("@Bean method %s.%s is non-static and returns an object " +
                                    "assignable to Spring's BeanFactoryPostProcessor interface. This will " +
                                    "result in a failure to process annotations such as @Autowired, " +
                                    "@Resource and @PostConstruct within the method's declaring " +
                                    "@Configuration class. Add the 'static' modifier to this method to avoid " +
                                    "these container lifecycle issues; see @Bean javadoc for complete details.",
                            beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
                }
                return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
            }

            return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
        }
// 当前方法一定是通过 @Confiuration类中full模式被代理的@Bean方法
//相当于用户直接使用方法获取bean
        private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
                ConfigurableBeanFactory beanFactory, String beanName) {

            // The user (i.e. not the factory) is requesting this bean through a call to
            // the bean method, direct or indirect. The bean may have already been marked
            // as 'in creation' in certain autowiring scenarios; if so, temporarily set
            // the in-creation status to false in order to avoid an exception.
            boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
            try {
                if (alreadyInCreation) {
// 如果是创建中,则先设置为false,防止异常情况
                    beanFactory.setCurrentlyInCreation(beanName, false);
                }
// 处理@Bean 方法中通过参数 @Autowired其他bean
                boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
// 如果@Bean返回的bean是单例,并且通过@Bean方法注入了其他bean
                if (useArgs && beanFactory.isSingleton(beanName)) {
                    // Stubbed null arguments just for reference purposes,
                    // expecting them to be autowired for regular singleton references?
                    // A safe assumption since @Bean singleton arguments cannot be optional...
                    for (Object arg : beanMethodArgs) {
                        if (arg == null) {
// 如果其他bean有没有注入成功的设置 参数为false
                            useArgs = false;
                            break;
                        }
                    }
                }
// 如果参数都注入则一起通过bean工厂获取,如果有的没注入成功则直接获取当前bean
                Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
                        beanFactory.getBean(beanName));
// 如果@Bean返回的 bean type 和当前使用beanName从工厂获取的bean不一致
                if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
                    // Detect package-protected NullBean instance through equals(null) check
// 如果是没有获取到bean 不做什么,后续返回null
                    if (beanInstance.equals(null)) {
                        if (logger.isDebugEnabled()) {
                            logger.debug(String.format("@Bean method %s.%s called as bean reference " +
                                    "for type [%s] returned null bean; resolving to null value.",
                                    beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
                                    beanMethod.getReturnType().getName()));
                        }
                        beanInstance = null;
                    }
                    else {
                        String msg = String.format("@Bean method %s.%s called as bean reference " +
                                "for type [%s] but overridden by non-compatible bean instance of type [%s].",
                                beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
                                beanMethod.getReturnType().getName(), beanInstance.getClass().getName());
                        try {
// 尝试从 工厂获取 BeanDefinition
                            BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
                            msg += " Overriding bean of same name declared in: " + beanDefinition.getResourceDescription();
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            // Ignore - simply no detailed message then.
                        }
                        throw new IllegalStateException(msg);
                    }
                }
// 从threadLocal查看当前 工厂正在调用的 工厂方法
                Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
                if (currentlyInvoked != null) {
// 当前工厂在运行 方法不为空时
                    String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
// 为当前@Bean 方法的bean 注入这个正在调用工厂方法bean作为依赖bean注册,这里不明白,后续会仔细研究一下                  beanFactory.registerDependentBean(beanName, outerBeanName);
                }
                return beanInstance;
            }
            finally {
                if (alreadyInCreation) {
// 刚才置为 false的状态重新置回                    beanFactory.setCurrentlyInCreation(beanName, true);
                }
            }
        }

        @Override
        public boolean isMatch(Method candidateMethod) {
// 适配器,当前拦截方法为了拦截@Bean的方法,还要排除 SetBeanFactory,并且@Bean的方法不可以返回 Object噢
            return (candidateMethod.getDeclaringClass() != Object.class &&
                    !BeanFactoryAwareMethodInterceptor.isSetBeanFactory(candidateMethod) &&
                    BeanAnnotationHelper.isBeanAnnotated(candidateMethod));
        }

//  省略部分代码...
    

上面跟踪了整体@Configuration full模式的 setBeanFactory方法拦截
以及对@Bean注解的方法拦截逻辑,通过适配器以及spring的cglib动态代理的组合实现了重复调用@Bean注解的方法只初始化一次bean

  1. 接下来看创建bean的流程。通过逆向来看


    生成代理的类

    一看,是我们很熟悉的BeanPostProcessor钩子接口

// 先看看这个类实现了哪些钩子, 对于bean操作的钩子就是BeanDefinitionRegistryPostProcessor 含有两个维度的 bean钩子,一个是BeanFactoryPostProcessor#postProcessBeanFactory 工厂的钩子一个是bean注册器的钩子,这两个钩子是重点

BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry 
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
        PriorityOrdered, ResourceLoaderAware, ApplicationStartupAware, BeanClassLoaderAware, EnvironmentAware

那么我们先从 beanFactory钩子来看

    @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 当前@Configuration的bean工厂没有到达钩子的调用时机,是不允许去创建代理的,需要再去调用BeanDefinitionRegistryPostProcessor 的钩子,实际是再去重新注入一遍@Configuration的bean
            // BeanDefinitionRegistryPostProcessor hook apparently not supported...
            // Simply call processConfigurationClasses lazily at this point then.
            processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
        }
// @Configuration full 模式进行代理
        enhanceConfigurationClasses(beanFactory);
// 这是动态加入一个新得钩子先具体看看逻辑
        beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
    }

我们先看ImportAwareBeanPostProcessor这个内部类逻辑,然后再看enhanceConfigurationClasses方法生成代理,然后看processConfigBeanDefinitions

private static class ImportAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
        private final BeanFactory beanFactory;
        public ImportAwareBeanPostProcessor(BeanFactory beanFactory) {
            this.beanFactory = beanFactory;
        }
        @Override
        public PropertyValues postProcessProperties(@Nullable PropertyValues pvs, Object bean, String beanName) {
            // Inject the BeanFactory before AutowiredAnnotationBeanPostProcessor's
            // postProcessProperties method attempts to autowire other configuration beans.
// 这是我们最初看到的 生成的代理类标记的接口,在这里对它setBeanFactory钩子调用, 这就找到了我们动态生成的cglib代理类是如何调用setBeanFactory钩子的,这里会进行调用同时代理会拦截setBeanFactory方法将成员变量的BeanFactory传入赋值
            if (bean instanceof EnhancedConfiguration) {
                ((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory);
            }
            return pvs;
        }
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) {
            if (bean instanceof ImportAware) {
// 如果这个@Configuration类是full模式,并且
                ImportRegistry ir = this.beanFactory.getBean(IMPORT_REGISTRY_BEAN_NAME, ImportRegistry.class);
                AnnotationMetadata importingClass = ir.getImportingClassFor(ClassUtils.getUserClass(bean).getName());
                if (importingClass != null) {
                    ((ImportAware) bean).setImportMetadata(importingClass);
                }
            }
            return bean;
        }
    }

下面再来看看 enhanceConfigurationClasses方法的逻辑

    public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
        StartupStep enhanceConfigClasses = this.applicationStartup.start("spring.context.config-classes.enhance");
        Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
        for (String beanName : beanFactory.getBeanDefinitionNames()) {
// 获取beanDefinition
            BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
// 获取configurationClass 的属性
            Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
            AnnotationMetadata annotationMetadata = null;
            MethodMetadata methodMetadata = null;
// 如果是注解注入bean的获取注解属性,其实现在都不使用xml,都是使用@Component及其派生
            if (beanDef instanceof AnnotatedBeanDefinition) {
                AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDef;
                annotationMetadata = annotatedBeanDefinition.getMetadata();
                methodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata();
            }
// 使用注解@Configuation,因为可以获取到@Configuration特有的属性并且是注解注入bean则一定是 @Configuration
            if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
                // Configuration class (full or lite) or a configuration-derived @Bean method
                // -> eagerly resolve bean class at this point, unless it's a 'lite' configuration
                // or component class without @Bean methods.
                AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
                if (!abd.hasBeanClass()) {
// 通过@Configuration的proxyBeanMethods属性的值和
                    boolean liteConfigurationCandidateWithoutBeanMethods =
                            (ConfigurationClassUtils.CONFIGURATION_CLASS_LITE.equals(configClassAttr) &&
                                annotationMetadata != null && !ConfigurationClassUtils.hasBeanMethods(annotationMetadata));
                    if (!liteConfigurationCandidateWithoutBeanMethods) {
                        try {
                            
// 如果是 full 模式放入 beanClassLoader
abd.resolveBeanClass(this.beanClassLoader);
                        }
                        catch (Throwable ex) {
                            throw new IllegalStateException(
                                    "Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
                        }
                    }
                }
            }
            if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
                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.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
                    logger.info("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'.");
                }
// 将full模式的 @Configuration 收集
                configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
            }
        }
        if (configBeanDefs.isEmpty() || NativeDetector.inNativeImage()) {
// 没有full模式直接返回
            // nothing to enhance -> return immediately
            enhanceConfigClasses.end();
            return;
        }
// 开始通过 spring aop包下封装的cglib动态代理对@Configuration进行代理
        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
            
// 这又是老朋友了, 将@EnableAspectJAutoProxy的proxyTargetClass属性设置为true,就是标记当前类使用cglib代理,默认false使用jdk基于接口的代理
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
            // Set enhanced subclass of the user-specified bean class
            Class<?> configClass = beanDef.getBeanClass();
// 又见到新朋友了,这里是调用上面代码的ConfigurationClassEnhancer#enhance生成代理class对象
            Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
            if (configClass != enhancedClass) {
                if (logger.isTraceEnabled()) {
                    logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
                            "enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
                }
// 将 bean的class替换为动态代理子类
                beanDef.setBeanClass(enhancedClass);
            }
        }
        enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet().size())).end();
    }

然后processConfigBeanDefinitions 方法

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
        String[] candidateNames = registry.getBeanDefinitionNames();

        for (String beanName : candidateNames) {
// 显示已经进入到注册器的bean 全部取出来遍历
            BeanDefinition beanDef = registry.getBeanDefinition(beanName);
            if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
// 如果是当前ConfigurationClassPostProcessor 这个bean忽略
                if (logger.isDebugEnabled()) {
                    logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
                }
            }
            else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
// 如果是  @Configuration 的注入的bean 则收集,这个方法不跟进去了,这里收集@Configuration时会过滤掉BeanFactoryPostProcessor,BeanPostProcessor,AopInfrastructureBean,EventListenerFactory子类,这里不太明白。。。以后多看看spring的逻辑或许会懂
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        }

        // Return immediately if no @Configuration classes were found
        if (configCandidates.isEmpty()) {
            return;
        }
        // Sort by previously determined @Order value, if applicable
        configCandidates.sort((bd1, bd2) -> {
            int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
            int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
            return Integer.compare(i1, i2);
        });
        // Detect any custom bean name generation strategy supplied through the enclosing application context
        SingletonBeanRegistry sbr = null;
        if (registry instanceof SingletonBeanRegistry) {
            sbr = (SingletonBeanRegistry) registry;
            if (!this.localBeanNameGeneratorSet) {
                BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
                        AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
                if (generator != null) {
                    this.componentScanBeanNameGenerator = generator;
                    this.importBeanNameGenerator = generator;
                }
            }
        }

        if (this.environment == null) {
            this.environment = new StandardEnvironment();
        }
// 这里看到了 如果发现@Configuration类会将其解析
        // Parse each @Configuration class
        ConfigurationClassParser parser = new ConfigurationClassParser(
                this.metadataReaderFactory, this.problemReporter, this.environment,
                this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// 用于收集的容器
        Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
        Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
        do {
            StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
// 一个一个bean来解析 @Configuration 并验证
            parser.parse(candidates);
            parser.validate();

            Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
// 防止重复解析,将已经处理过的 移除
            configClasses.removeAll(alreadyParsed);

            // Read the model and create bean definitions based on its content
            if (this.reader == null) {
                this.reader = new ConfigurationClassBeanDefinitionReader(
                        registry, this.sourceExtractor, this.resourceLoader, this.environment,
                        this.importBeanNameGenerator, parser.getImportRegistry());
            }
// 这里是 注入 @Bean的 bean噢,也就是@Bean的实现就是通过这个方法,当前方法不停的检测是否有新的 @Configuration注入然后到这里进行@Bean的注入
            this.reader.loadBeanDefinitions(configClasses);
            alreadyParsed.addAll(configClasses);
            processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

            candidates.clear();
// 如果当前程序在刚进入方法,到当前代码行有新的bean装载,需要处理
            if (registry.getBeanDefinitionCount() > candidateNames.length) {
// 获取新得 bean 包含旧的
                String[] newCandidateNames = registry.getBeanDefinitionNames();
                Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
                Set<String> alreadyParsedClasses = new HashSet<>();
// 将已经装载的 @Configuration bean放入上面的set容器
                for (ConfigurationClass configurationClass : alreadyParsed) {
                    alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
                }
// 遍历所有新的bean 包含已经装载的
                for (String candidateName : newCandidateNames) {
                    if (!oldCandidateNames.contains(candidateName)) {
// 如果是新的bean
                        BeanDefinition bd = registry.getBeanDefinition(candidateName);
                        if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                                !alreadyParsedClasses.contains(bd.getBeanClassName())) {
// 如果是 @Configuration 的bean同时是未装载过的收集
                            candidates.add(new BeanDefinitionHolder(bd, candidateName));
                        }
                    }
                }
// 旧的全部 bean names 引用换成新的 
                candidateNames = newCandidateNames;
            }
        }
// 一直发现有新的 @Configuration 装载到 bean注册器才跳出,那么就可以解释方法调用方是在未发现已经注册的对应 @Configuration到这个方法再进行处理,并且这个注册器的bean是要缓存到当前类对象中通过postProcessBeanDefinitionRegistry 也不停的调用当前方法
        while (!candidates.isEmpty());

        // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
// 支持 ImportAware
        if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
            
//这里是为了支持@Configuration类上的@Import注入
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
        }
// 产生新的载入动作 清除缓存
        if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
            // Clear cache in externally provided MetadataReaderFactory; this is a no-op
            // for a shared cache since it'll be cleared by the ApplicationContext.
            ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
        }
    }

总结

  1. BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry通过注册器来对当前beanFactory的bean进行整理操作
  2. BeanFactoryPostProcessor#postProcessBeanFactory 后于上面方法的钩子时机对已经注册的@Configuration类进行代理并考虑懒加载
  3. 使用spring-aop的cglib动态代理的封装对指定 setBeanFactory和@Bean注解到的方法进行代理拦截
  4. 通过InstantiationAwareBeanPostProcessor#postProcessProperties和postProcessBeforeInitialization方法对生成的代理类进ImportAware和setBeanFactory自动连接
  5. 使用cglib拦截指定的方法进行逻辑操作,当然我们就拦截了setBeanFactory和 @Bean注解的方法进行操作
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容