• @Configuration和@Component


    @Configuration注解和@Component注解的区别

    首先看下@Configuration这个注解

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component
    public @interface Configuration {
    
    	@AliasFor(annotation = Component.class)
    	String value() default "";
    	
    	boolean proxyBeanMethods() default true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    可以发现其实@Configuration注解本质上也是一个@Component注解.

    @Configuration
    @ComponentScan("com.aiqiong.admin")
    public class AppConfig {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    @Component
    public class A {
    
    }
    
    • 1
    • 2
    • 3
    • 4
        public static void main(String[] args) {
            AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
            A a = (A) annotationConfigApplicationContext.getBean("a");
            System.out.println("a = " + a);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    运行结果
    在这里插入图片描述
    可以看到A此时是一个普通的对象
    把A类上的注解换成@Configuration

    @Configuration
    public class A {
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    运行结果:
    在这里插入图片描述
    可以看到加上Configuration注解之后,A变成了一个cglib的代理对象.

    @Configuration注解生成cglib代理的作用

    场景:

    
    @Component
    public class AppConfig {
    
        @Bean
        public B b(){
            B b = new B();
            b.setA(a());
            return b;
        }
    
    
        @Bean
        public A a(){
            return new A();
        }
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    public class A {
    
        public A(){
            System.out.println("A....");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    通过控制台的输出信息可以看到,其实A对象被创建了两次在这里插入图片描述
    换成@Configuration注解呢

    @Configuration
    public class AppConfig {
    
        @Bean
        public B b(){
            B b = new B();
            b.setA(a());
            return b;
        }
    
        @Bean
        public A a(){
            return new A();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    此时A只创建一次.
    在这里插入图片描述
    所以@Configuration注解就是为了避免用户显式地去调用@Bean方法,造成破坏了@Bean方法的bean的单例,而@Configuration注解能够做到这样避免用户显式调用@Bean方法的原理就是通过创建对应的配置类cglib代理对象去实现的.
    下面我们重点看一下@Configuraton注解底层是怎么通过cglib代理去实现@Bean方法不被用户显式调用.

    @Configuration动态代理的实现原理

    ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor接口,而BeanDefinitionRegistryPostProcessor接口又是继承于BeanFactoryPostProcessor接口,众所周知BeanFactoryPostProcessor接口接口是一个BeanFactory的后置处理接口,也就是在BeanFactory初始化之后会调用该接口的postProcessBeanFactory方法,也就是上面的方法,其中里面会再调用enhanceConfigurationClasses方法,该方法就是生成cglib代理的关键方法

    	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);
    		}
    		// 生成配置类cglib代理
    		enhanceConfigurationClasses(beanFactory);
    		beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
    		Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
    		// 遍历当前spring容器中所有的bd名称,这个for循环的目的就是找到所有全配置类(加了@Configuration注解的配置类)
    		for (String beanName : beanFactory.getBeanDefinitionNames()) {
    			// 根据bd名称获取到bd
    			BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
    			// 获取到CONFIGURATION_CLASS_ATTRIBUTE对应的属性值
    			Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
    			MethodMetadata methodMetadata = null;
    			if (beanDef instanceof AnnotatedBeanDefinition) {
    				methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata();
    			}
    			if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
    				// Configuration class (full or lite) or a configuration-derived @Bean method
    				// -> resolve bean class at this point...
    				AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
    				if (!abd.hasBeanClass()) {
    					try {
    						abd.resolveBeanClass(this.beanClassLoader);
    					}
    					catch (Throwable ex) {
    						throw new IllegalStateException(
    								"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
    					}
    				}
    			}
    			// 条件成立:说明这个bd对应的是一个全配置类
    			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)) {
    				
    				configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
    			}
    		}
    		// 条件成立:没有需要被增强的配置类
    		if (configBeanDefs.isEmpty()) {
    			// nothing to enhance -> return immediately
    			return;
    		}
    		// 如果这个类是一个全配置类,那么就使用cglib进行代理增强,目的是防止@Bean方法的手动重复调用造成单例的破坏
    		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);
    			// Set enhanced subclass of the user-specified bean class
    			Class<?> configClass = beanDef.getBeanClass();
    			// 给这个全配置类创建一个cglib增强后的Class对象
    			Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
    			if (configClass != enhancedClass) {
    				// 把cglib代理的Class对象设置到这个全配置类的bd中
    				beanDef.setBeanClass(enhancedClass);
    			}
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    上面代码其实分成了两大步骤:
    第一步骤是用来找到扩展属性CONFIGURATION_CLASS_ATTRIBUTE对应的值等于CONFIGURATION_CLASS_FULL的BeanDefinition.
    这个属性是在执行postProcessBeanFactory方法之前,spring会解析所有的配置类,然后解析成对应的BeanDefinition.
    而BeanDefinition又分成了两种,一种是全配置类,一种是半配置类.

    • 全配置类:加了@Configuration注解并且proxyBeanMethods属性等于true
    • 半配置类:加了@Component,@ComponentScan,@Import,@ImportResource这几个注解,或者@Configuration注解并且proxyBeanMethods属性等于false

    对于全配置类CONFIGURATION_CLASS_ATTRIBUTE值等于CONFIGURATION_CLASS_FULL
    对于半配置类CONFIGURATION_CLASS_ATTRIBUTE值等于CONFIGURATION_CLASS_LITE

    第二步是把上面找出来的BeanDefinition创建cglib代理.使用的就是ConfigurationClassEnhancer这个工具类.

    创建代理对象详解

    概述

    	public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
    		if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
    			
    			return configClass;
    		}
    		Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
    		
    		return enhancedClass;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    	private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
    		Enhancer enhancer = new Enhancer();
    		enhancer.setSuperclass(configSuperClass);
    		enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
    		enhancer.setUseFactory(false);
    		enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    		enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
    		enhancer.setCallbackFilter(CALLBACK_FILTER);
    		enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
    		return enhancer;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    上面都比较简单,就是常规的创建代理对象需要的参数

    	private Class<?> createClass(Enhancer enhancer) {
    		Class<?> subclass = enhancer.createClass();
    		Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
    		return subclass;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    最后调用enhancer的createClass方法,就可以得到一个增强后的Class对象,返回出去之后把这个增强的Class对象设置到BeanDefinition中就可以了
    创建代理对象参数详解
    (1) CallbackFilter

    enhancer.setCallbackFilter(CALLBACK_FILTER);
    
    • 1

    作用:当执行目标方法的时候会被accept方法拦截,在accept方法中会根据传入的目标方法去返回一个Callback增强.
    通过这个CallbackFilter就可以实现调用不同的方法使用不同的增强Callback.spring这里传入的是ConditionalCallbackFilter,这个CallbackFilter在创建的时候需要传入一个Callback数组.
    这个数组会被accept方法过滤,返回一个具体的Callback返回.

    private static class ConditionalCallbackFilter implements CallbackFilter {
    
    		private final Callback[] callbacks;
    
    		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();
    			}
    		}
    		// 
    		@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)) {
    					return i;
    				}
    			}
    			throw new IllegalStateException("No callback available for method " + method.getName());
    		}
    
    		public Class<?>[] getCallbackTypes() {
    			return this.callbackTypes;
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    上面提到一个Callback数组,那么这个数组中的元素是啥呢?

    	private static final Callback[] CALLBACKS = new Callback[] {
    			new BeanMethodInterceptor(),
    			new BeanFactoryAwareMethodInterceptor(),
    			// 不进行增强
    			NoOp.INSTANCE
    	};
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    根据对应isMatch方法来看一下另外两个都是什么时候回被调用

    1、BeanMethodInterceptor

    		public boolean isMatch(Method candidateMethod) {
    		     // 不是Object对象、不是setBeanFactory方法,并且方法上要有@Bean注解
    			return (candidateMethod.getDeclaringClass() != Object.class &&
    					!BeanFactoryAwareMethodInterceptor.isSetBeanFactory(candidateMethod) &&
    					BeanAnnotationHelper.isBeanAnnotated(candidateMethod));
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2、BeanFactoryAwareMethodInterceptor

    		public boolean isMatch(Method candidateMethod) {
    			return isSetBeanFactory(candidateMethod);
    		}
    		
    		public static boolean isSetBeanFactory(Method candidateMethod) {
    			// 是setBeanFactory方法
    			return (candidateMethod.getName().equals("setBeanFactory") &&
    					candidateMethod.getParameterCount() == 1 &&
    					BeanFactory.class == candidateMethod.getParameterTypes()[0] &&
    					BeanFactoryAware.class.isAssignableFrom(candidateMethod.getDeclaringClass()));
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    那么最后我们返回的是哪一个增强器呢?
    (2) EnhancedConfiguration

    enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
    
    • 1
    public interface EnhancedConfiguration extends BeanFactoryAware {
    }
    
    • 1
    • 2

    所以自然地cglib代理对象中自然就会有这个BeanFactoryAware接口的setBeanFactory方法了.
    所以可以回答上面一个问题了,创建代理的时候使用的增强器是BeanFactoryAwareMethodInterceptor
    那么setBeanFactory方法是在什么时候被调用的呢?
    这就要回顾之前讲到的Bean的生命周期了.如果一个bean实现了BeanFactoryAware接口的话,在实例化的过程中会回调BeanFactoryAware接口的setBeanFactory方法,然后在spring回调setBeanFactory方法的时候,BeanFactoryAwareMethodInterceptor这个Callback就能拦截到,执行intercept方法中的增强逻辑.
    在intercept方法中做的其实就是把回调回来的BeanFactory对象赋值给属性名称为beanFactory的属性.
    beanFactory这个属性是哪里的?在哪里设置的呢?

    (3) beanFactory

    	enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
    
    • 1

    setStrategy属性可以设置生成代理类的class文件字节码策略,这里具体设置的策略是BeanFactoryAwareGeneratorStrategy.

    	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() {
    					// 给生成的代理类添加一个属性
    					// 属性名为 beanFactory
    					// 访问域是public
    					// 属性类型是BeanFactory
    					declare_field(Constants.ACC_PUBLIC, BEAN_FACTORY_FIELD, Type.getType(BeanFactory.class), null);
    					super.end_class();
    				}
    			};
    			return new TransformingClassGenerator(cg, transformer);
    		}
    
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    	private static final String BEAN_FACTORY_FIELD = "$$beanFactory";
    
    • 1

    总结下BeanFactoryAwareMethodInterceptor这个Callback的作用了,它的作用就是在spring回调BeanFactoryAware接口的seetBeanFactory方法的时候,把回调的BeanFactory对象赋值给
    beanFactory属性,而这个属性的由来就是cglib在创建代理类的时候添加进来的.

    下面讲讲另外一种增强器
    BeanMethodInterceptor

    		public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
    					MethodProxy cglibMethodProxy) throws Throwable {
    			// 获取到$$beanFactory属性的值,也就是BeanFactory对象
    			ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
    			String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
    
    			// Determine whether this bean is a scoped-proxy
    			if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
    				String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
    				if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
    					beanName = scopedBeanName;
    				}
    			}
    
    			
    			if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
    					factoryContainsBean(beanFactory, beanName)) {
    				Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
    				if (factoryBean instanceof ScopedProxyFactoryBean) {
    					
    				}
    				else {
    					// It is a candidate FactoryBean - go ahead with enhancement
    					return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
    				}
    			}
    
    			// 条件成立:说明此时spring正在执行反射执行这个@Bean方法
    			if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
    				// 调用父类的原始@Bean方法返回bean实例,返回的bean实例会注册到spring容器中
    				return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
    			}
    
    			// 代码来到这里说明此时的@Bean方法并不是由spring调用的,而是用户自身的代码显示调用的
       			// 这种情况也就是在@Bean方法B中调用@Bean方法A,
       			// 在调用@Bean方法B的时候上面的条件就不会成立,所以会执行到这里
       			// 从BeanFactory中获取bean
    			return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    		private boolean isCurrentlyInvokedFactoryMethod(Method method) {
    			Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
    			return (currentlyInvoked != null && method.getName().equals(currentlyInvoked.getName()) &&
    					Arrays.equals(method.getParameterTypes(), currentlyInvoked.getParameterTypes()));
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    其中比较重要的是Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod()
    这里就要提到spring实例化bean的时候了.看下面这里实例化bean的代码

    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
          @Nullable Object factoryBean, final Method factoryMethod, Object... args) {
     
       try {
          if (System.getSecurityManager() != null) {
             AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                ReflectionUtils.makeAccessible(factoryMethod);
                return null;
             });
          }
          else {
             ReflectionUtils.makeAccessible(factoryMethod);
          }
     
          Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
          try {
             // 把要执行的工厂方法放到currentlyInvokedFactoryMethod中
             currentlyInvokedFactoryMethod.set(factoryMethod);
             // 通过反射执行工厂实例的工厂方法
             Object result = factoryMethod.invoke(factoryBean, args);
             if (result == null) {
                result = new NullBean();
             }
             return result;
          }
          finally {
             if (priorInvokedFactoryMethod != null) {
                currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
             }
             else {
                currentlyInvokedFactoryMethod.remove();
             }
          }
       }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    可以看到spring实例化bean的时候会通过反射去调用这个bean所在的配置类的@Bean方法,在调用前会把这个@Bean方法放到currentlyInvokedFactoryMethod中.这一步是spring实例化bean的时候触发的,如果手动调这个@Bean方法,根本不会调用上面的方法currentlyInvokedFactoryMethod中也就不会有这个@Bean方法.
    所以isCurrentlyInvokedFactoryMethod方法里的

    Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
    
    • 1

    如果currentlyInvoked为空,说明是手动调用的,并且返回false,不为空是通过spring反射调用的,并且返回true.
    如果返回的是false,则直接就执行resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);

    		private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
    				ConfigurableBeanFactory beanFactory, String beanName) {
    
    			// 判断当前bean是否正在创建
    			boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
    			try {
    				if (alreadyInCreation) {
    					beanFactory.setCurrentlyInCreation(beanName, false);
    				}
    				boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
    				if (useArgs && beanFactory.isSingleton(beanName)) {
    				
    					for (Object arg : beanMethodArgs) {
    						if (arg == null) {
    							useArgs = false;
    							break;
    						}
    					}
    				}
    				// 从spring容器中获取这个bean
    				Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
    						beanFactory.getBean(beanName));
    				if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
    					// Detect package-protected NullBean instance through equals(null) check
    					if (beanInstance.equals(null)) {
    						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 = 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);
    					}
    				}
    				Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
    				if (currentlyInvoked != null) {
    					String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
    					// 注册两个bean之间的依赖关系
    					beanFactory.registerDependentBean(beanName, outerBeanName);
    				}
    				return beanInstance;
    			}
    			finally {
    				if (alreadyInCreation) {
    					beanFactory.setCurrentlyInCreation(beanName, true);
    				}
    			}
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    总结
    Configuration注解能够使得加了它的对应的配置类在spring容器中是一个cglib代理bean,让配置类实例变成cglib代理实例的作用就是防止@Bean方法B又调用@Bean方法A的这种场景破坏了bean的单例性。
    解决这种场景的原理就是在spring实例化@Bean方法B对应的bean的时候,会通过反射调用配置类的@Bean方法B,在反射调用之前@Bean方法B放到currentlyInvokedFactoryMethod中,然后由于配置类已经是一个cglib代理对象了,
    所以会被BeanMethodInterceptor这个Callback进行拦截增强,此时判断到currentlyInvokedFactoryMethod中存在方法B,那么就直接执行这个@Bean方法B了,而@Bean方法B中又调用了@Bean方法A,
    所以此时在执行@Bean方法B的时候,@Bean方法A也会被BeanMethodInterceptor这个Callback所拦截增强,但是,此时currentlyInvokedFactoryMethod中的方法是@Bean方法B,所以isCurrentlyInvokedFactoryMethod方法判断返回的是false,也就是走resolveBeanReference方法从spring容器中去获取@Bean方法A对应的bean.

    该文章是转载大佬的为何加上@Configuration注解的类会生成cglib代理?

  • 相关阅读:
    极客的浪漫「GitHub 热点速览 v.22.41」
    【C++ 构造函数和析构函数:对象生命周期的关键】
    贪心算法,删数问题
    数据仓库之数据冗余规范
    【Linux开发】如何在Ubuntu系统创建新用户,并且用MobaXterm连接linux服务器,创建session?
    Docker学习资料集(从入门到实践)
    可以部署个人大模型的在线平台
    v 3 + vite + ts 自适应布局(postcss-pxtorem)
    GD32(4)存储管理
    【Linux】3.切换操作系统
  • 原文地址:https://blog.csdn.net/qq_40708942/article/details/126777991