Spring中@Configuration源码深度解析(二)

      在Spring中@Configuration源码深度解析(一)中已经说到了执行代码块4PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors方法的第一个重要方法: invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);会将普通注解类转换成beanDefinition对象。

      下面让我们说一下这个方法第二个重要方法:invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);该方法会执行实现了BeanFactoryPostProcessor接口的postProcessBeanFactory方法(由于ConfigurationClassPostProcessor实现BeanDefinitionRegistryPostProcessor接口,而BeanDefinitionRegistryPostProcessor 又继承了BeanFactoryPostProcessor接口,所以在这篇文章的重点是讲ConfigurationClassPostProcessor的postProcessBeanFactory方法)。

代码块1.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors方法

private static void invokeBeanFactoryPostProcessors(
		Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
	//执行所有BeanFactoryPostProcessor的postProcessBeanFactory方法
	for (BeanFactoryPostProcessor postProcessor : postProcessors) {
		postProcessor.postProcessBeanFactory(beanFactory);
	}
}

       该方法最终调用ConfigurationClassPostProcessor的postProcessBeanFactory方法,完成会加了@Configuration注解类的增强。

    代码块2.ConfigurationClassPostProcessor#postProcessBeanFactory方法

@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);
	}
	//1. 给加了@Configuration注解的配置类产生cglib代理
	enhanceConfigurationClasses(beanFactory);
	//2. 向容器中注入ImportAwareBeanPostProcessor,其是一个bean的后置处理器,
	beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

      第1步:给加了@Configuration注解的配置类产生cglib代理 ,并给它设置成EnhancedConfiguration的子类,查看代码块3

      第2步:向容器中注入ImportAwareBeanPostProcessor,ImportAwareBeanPostProcessor是一个bean的后置处理器,其作用就是判断一个类是不是EnhancedConfiguration的子类,如果是把bean工厂赋值给他,这样加了@Configuration注解的类,就可以直接去容器中获取bean

代码块3. ConfigurationClassPostProcessor#enhanceConfigurationClasses方法

public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
	//存放所有为full类型的BeanDefinition,也就是加了@Configuration注解的
	Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
	//1.从容器中拿到所有BeanDefinition的名称
	for (String beanName : beanFactory.getBeanDefinitionNames()) {
		BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
		//2.判断是否是一个全注解类
		//扫描是全注解类?full和lite的关系
		if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
			if (!(beanDef instanceof AbstractBeanDefinition)) {
				throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
						beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
			}
			//3.将为full类型的加到Map中
			configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
		}
	}
	//4.没有full类型的就返回
	if (configBeanDefs.isEmpty()) {
		// nothing to enhance -> return immediately
		return;
	}
	//创建一个增强器
	ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
	//5.遍历这个Map
	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
			// 6.获取类的Class进行增强
			Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
			if (configClass != null) {
				//7. 完成对全注解类的cglib代理
				Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
				if (configClass != enhancedClass) {
					//8.将增强后的cglib代理类设置成BeanDefinition的BeanClass
					beanDef.setBeanClass(enhancedClass);
				}
			}
		}
		catch (Throwable ex) {
			throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
		}
	}
}

      在第2步会判断是否是full类型的,如果去就加到一个Map中,看代码块4.

      在第7步中会完成会full类型的代理,使用的是cglib代理,这是你就知道了为什么加了@Configuration的类不能是final类型的了(使用cglib代理会继承需要增强的类,而你加了final说明这个类不能有子类了)看代码块5.

      第8步:将增强后的cglib代理类设置成BeanDefinition的beanClass,因为在后面Spring进行实例化bean的时候,是根据BeanDefinition的beanClass来进行的,所以在此将beanClass改了之后,就能在下面使用这个代理类来进行实例化。

代码块4:ConfigurationClassUtils#isFullConfigurationClass方法

    

public static boolean isFullConfigurationClass(BeanDefinition beanDef) {
    //判断BeanDefinition的CONFIGURATION_CLASS_ATTRIBUTE属性是不是full
	return CONFIGURATION_CLASS_FULL.equals(beanDef.getAttribute(CONFIGURATION_CLASS_ATTRIBUTE));
}

      在Spring中@Configuration源码深度解析(一)中加了@Configuration注解的类会被设置成full,所以会被加入到configBeanDefs的Map中。

代码块5:ConfigurationClassEnhancer#enhance方法

public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
	//1. isAssignableFrom方式是判断父类.class.isAssignableFrom(子类.class)
	//isAssignableFrom()方法是从类继承的角度去判断,是判断是否为某个类的父类
	//如果是EnhancedConfiguration的子类,说明被代理过
	if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
		return configClass;
	}
	
	//2. 没有被代理cglib代理,则进行cglib代理
	Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
	return enhancedClass;
}

       在第2步中有两个方法一个是newEnhancer方法(看代码块6),该方法是创建一个增强对象,一个是createClass方法,根据得到一个增强后的Class对象, 

       注意在newEnhancer方法会生成一个Enhancer对象,用于在createClass中进行得到一个增强后的Class对象

代码块6:ConfigurationClassEnhancer#newEnhancer方法

private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
	Enhancer enhancer = new Enhancer();
	//1. 增强父类,地球人都知道cglib是基于继承来的
	//设置需要被增强的对象为代理对象的父类
	enhancer.setSuperclass(configSuperClass);
	//2. 增强接口,为什么要增强接口?
	//便于判断,表示一个类以及被增强了,EnhancedConfiguration继承了BeanFactoryAware接口
	//所以代理类可以拿到BeanFactory工厂
	enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
	//不继承Factory接口
	enhancer.setUseFactory(false);
	enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
	// 3. BeanFactoryAwareGeneratorStrategy是一个生成策略
	// 主要为生成的CGLIB类中添加成员变量$$beanFactory
	// 同时基于接口EnhancedConfiguration的父接口BeanFactoryAware中的setBeanFactory方法,
	// 设置此变量的值为当前Context中的beanFactory,这样一来我们这个cglib代理的对象就有了beanFactory
	//有了factory就能获得对象,而不用去通过方法获得对象了,因为通过方法获得对象不能控制器过程
	//该BeanFactory的作用是在this调用时拦截该调用,并直接在beanFactory中获得目标bean
	enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
	//4. 过滤方法,不能每次都去new
	enhancer.setCallbackFilter(CALLBACK_FILTER);
	enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
	return enhancer;
}

//该类为ConfigurationClassEnhancer的内部类,继承了BeanFactoryAware接口
public interface EnhancedConfiguration extends BeanFactoryAware {
}

       在第2步中会给代理类设置一个ConfigurationClassEnhancer的接口,这个接口继承了BeanFactoryAware,让生成的代理类可以拿到BeanFactory对象。

       在第3步中会给代理类增加一个public的类型为BeanFactory,名为$$beanFactory字段的属性,看代码块7

       在第4步增强方法拦截器,在执行方法的时候,首先去容器中判断是否有这个bean,如果没有的话,才会执行这个方法,有的话,直接返回容器内部的bean,看代码块8

代码块7: BeanFactoryAwareGeneratorStrategy类:

private static class BeanFactoryAwareGeneratorStrategy extends DefaultGeneratorStrategy {

	@Nullable
	private final ClassLoader classLoader;

	public BeanFactoryAwareGeneratorStrategy(@Nullable ClassLoader classLoader) {
		this.classLoader = classLoader;
	}
	@Override
	protected ClassGenerator transform(ClassGenerator cg) throws Exception {
		ClassEmitterTransformer transformer = new ClassEmitterTransformer() {
			@Override
			public void end_class() {
			    //给代理类设置public类型为BeanFactory,名称是$$beanFactory的属性
				//Constants.ACC_PUBLIC = 0x0001
				//BEAN_FACTORY_FIELD = "$$beanFactory"
				declare_field(Constants.ACC_PUBLIC, BEAN_FACTORY_FIELD, Type.getType(BeanFactory.class), null);
				super.end_class();
			}
		};
		return new TransformingClassGenerator(cg, transformer);
	}
	
	//省略了一个方法
}

代码块8:看一下CALLBACK_FILTER

        

        在代码块6中的第4步,就是添加了CALLBACK_FILTER变量,然后这个两个里面有两个方法拦截器,一个是拦截标注了@Configuration注解的类里面的方法,一个是拦截BeanFactoryAware接口的setBeanFactory方法。

       对于拦截标注了@Configuration注解的类里面的方法,看代码块9

代码块9:ConfigurationClassEnhancer.BeanMethodInterceptor类

//ConfigurationClassEnhancer里面的内部类BeanMethodInterceptor
//用于拦截@Bean方法的调用,并直接从BeanFactory中获取目标bean,而不是通过执行方法。
private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
	@Override
	@Nullable
	public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
				MethodProxy cglibMethodProxy) throws Throwable {

		//enhancedConfigInstance 代理
		// 1. 通过enhancedConfigInstance中cglib生成的成员变量$$beanFactory获得beanFactory。
		ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
		// 2. 获得@Configuration注解中加了@Bean的bean的名称,如果没有指定,则使用方法作为bean的名称
		String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);

		// Determine whether this bean is a scoped-proxy
		Scope scope = AnnotatedElementUtils.findMergedAnnotation(beanMethod, Scope.class);
		if (scope != null && scope.proxyMode() != ScopedProxyMode.NO) {
			String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
			if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
				beanName = scopedBeanName;
			}
		}
               //3. 这里是将bean的名称加上"&"判断是不是FactoryBean类型的,如果是的话,就还需要对FactoryBean
	    //类型再进行一次代理,为什么?因为你获取的就是一个new出来的FactoryBean的,就不能保证单一性,
		//所以这这里需要对FactoryBean在进行一次拦截
		if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
				factoryContainsBean(beanFactory, beanName)) {
			Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
			if (factoryBean instanceof ScopedProxyFactoryBean) {
				// Scoped proxy factory beans are a special case and should not be further proxied
			}
			else {
				// It is a candidate FactoryBean - go ahead with enhancement
				return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
			}
		}

		//4. 一个非常牛逼的判断
		//判断到底是new 还是get
		//判断执行的方法和调用方法是不是同一个方法
		if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
			// 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.
			//调用父类的方法进行创建这个标注了@Bean注解的bean
			return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
		}
	    //5.从容器中拿bean实例
		return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
	}

	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.
		//6. 判断它是否正在创建
		boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
		try {
			if (alreadyInCreation) {
				beanFactory.setCurrentlyInCreation(beanName, false);
			}
			boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
			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) {
						useArgs = false;
						break;
					}
				}
			}
			//beanFactory.getBean
			//7. 这个方法就是从beanFactory容器中获取bean,beanFactory.getBean方法会去容器中进行查找bean,如果找不到则进行创建bean
			Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
					beanFactory.getBean(beanName));
			if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
				if (beanInstance.equals(null)) {
				
					beanInstance = null;
				}
				else {
				    //省略了这段代码,不重要
					throw new IllegalStateException();
				}
			}
			Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
			if (currentlyInvoked != null) {
				String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
				beanFactory.registerDependentBean(beanName, outerBeanName);
			}
			return beanInstance;
		}
		finally {
			if (alreadyInCreation) {
				beanFactory.setCurrentlyInCreation(beanName, true);
			}
		}
	}
}

       注意上面的方法不会在创建cglib代理的时候调用,只有在容器创建bean的时候调用,现在只是在动态的生成cglib代理对象,

 到这里关于@Configuration源码就看完了,更深层的细节我还没整懂,上面如果说的哪个地方有错误的可以指出来。

       另外,我们来可以来看一下使用cglib增强的类长什么样,可以帮助我们更好的理解cglib的原理:

       首先加上System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "C:\\class")的代码,然后运行这个mian方法就可以了,然后就可以去C盘中查看cglib生成的类。

public class Test01 {
	public static void main(String[] args) {
		System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "C:\\class");
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
	}
}

      这里我先贴出来没有增强之前的代码

@Configuration
@ComponentScan("com.luban.configuration")
public class Config {

	@Bean
	public School school() {
		return new School();
	}
}

       再贴出来增强后的代码: 

//继承了需要增强的Config类,并实现了EnhancedConfiguration接口
public class Config$$EnhancerBySpringCGLIB$$308299b4 extends Config implements ConfigurationClassEnhancer.EnhancedConfiguration {
  private boolean CGLIB$BOUND;
  
  public static Object CGLIB$FACTORY_DATA;
  
  private static final ThreadLocal CGLIB$THREAD_CALLBACKS;

  private static final Callback[] CGLIB$STATIC_CALLBACKS;
  
  private MethodInterceptor CGLIB$CALLBACK_0;
  
  private MethodInterceptor CGLIB$CALLBACK_1;
  
  private NoOp CGLIB$CALLBACK_2;
  
  private static Object CGLIB$CALLBACK_FILTER;
  
  private static final Method CGLIB$school$0$Method;
  
  private static final MethodProxy CGLIB$school$0$Proxy;
  
  private static final Object[] CGLIB$emptyArgs;
  
  private static final Method CGLIB$setBeanFactory$5$Method;
  
  private static final MethodProxy CGLIB$setBeanFactory$5$Proxy;
  //正如我们所说的,会有一个BeanFactory类型,名称为$$beanFactory的属性
  public BeanFactory $$beanFactory;
  
  static void CGLIB$STATICHOOK1() {
    CGLIB$THREAD_CALLBACKS = new ThreadLocal();
    CGLIB$emptyArgs = new Object[0];
    Class clazz1 = Class.forName("com.luban.configuration.Config$$EnhancerBySpringCGLIB$$308299b4");
    Class clazz2;
    CGLIB$setBeanFactory$5$Method = ReflectUtils.findMethods(new String[] { "setBeanFactory", "(Lorg/springframework/beans/factory/BeanFactory;)V" }, (clazz2 = Class.forName("org.springframework.beans.factory.BeanFactoryAware")).getDeclaredMethods())[0];
    CGLIB$setBeanFactory$5$Proxy = MethodProxy.create(clazz2, clazz1, "(Lorg/springframework/beans/factory/BeanFactory;)V", "setBeanFactory", "CGLIB$setBeanFactory$5");
    ReflectUtils.findMethods(new String[] { "setBeanFactory", "(Lorg/springframework/beans/factory/BeanFactory;)V" }, (clazz2 = Class.forName("org.springframework.beans.factory.BeanFactoryAware")).getDeclaredMethods());
    CGLIB$school$0$Method = ReflectUtils.findMethods(new String[] { "school", "()Lcom/luban/School;" }, (clazz2 = Class.forName("com.luban.configuration.Config")).getDeclaredMethods())[0];
    CGLIB$school$0$Proxy = MethodProxy.create(clazz2, clazz1, "()Lcom/luban/School;", "school", "CGLIB$school$0");
    ReflectUtils.findMethods(new String[] { "school", "()Lcom/luban/School;" }, (clazz2 = Class.forName("com.luban.configuration.Config")).getDeclaredMethods());
  }
  
  final School CGLIB$school$0() {
    return super.school();
  }
  //这个方法是被增强的方法
  public final School school() {
    if (this.CGLIB$CALLBACK_0 == null)
      CGLIB$BIND_CALLBACKS(this); 
	//进行方法的拦截
    return (this.CGLIB$CALLBACK_0 != null) ? 
	      (School)this.CGLIB$CALLBACK_0.intercept(this, CGLIB$school$0$Method, CGLIB$emptyArgs, CGLIB$school$0$Proxy) : super.school();
  }
  
  final void CGLIB$setBeanFactory$5(BeanFactory paramBeanFactory) throws BeansException {
    super.setBeanFactory(paramBeanFactory);
  }
  
  public final void setBeanFactory(BeanFactory paramBeanFactory) throws BeansException {
    if (this.CGLIB$CALLBACK_1 == null)
      CGLIB$BIND_CALLBACKS(this); 
    if (this.CGLIB$CALLBACK_1 != null) {
      (new Object[1])[0] = paramBeanFactory;
      return;
    } 
    super.setBeanFactory(paramBeanFactory);
  }
  
  public Config$$EnhancerBySpringCGLIB$$308299b4() {
    CGLIB$BIND_CALLBACKS(this);
  }
  
  public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] paramArrayOfCallback) {
    CGLIB$THREAD_CALLBACKS.set(paramArrayOfCallback);
  }
  
  public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] paramArrayOfCallback) {
    CGLIB$STATIC_CALLBACKS = paramArrayOfCallback;
  }
  
  private static final void CGLIB$BIND_CALLBACKS(Object paramObject) {
    Config$$EnhancerBySpringCGLIB$$308299b4 config$$EnhancerBySpringCGLIB$$308299b4 = (Config$$EnhancerBySpringCGLIB$$308299b4)paramObject;
    if (!config$$EnhancerBySpringCGLIB$$308299b4.CGLIB$BOUND) {
      config$$EnhancerBySpringCGLIB$$308299b4.CGLIB$BOUND = true;
      if (CGLIB$THREAD_CALLBACKS.get() == null) {
        CGLIB$THREAD_CALLBACKS.get();
        if (CGLIB$STATIC_CALLBACKS == null)
          return; 
      } 
      config$$EnhancerBySpringCGLIB$$308299b4.CGLIB$CALLBACK_2 = (NoOp)((Callback[])CGLIB$THREAD_CALLBACKS.get())[2];
      config$$EnhancerBySpringCGLIB$$308299b4.CGLIB$CALLBACK_1 = (MethodInterceptor)((Callback[])CGLIB$THREAD_CALLBACKS.get())[1];
      config$$EnhancerBySpringCGLIB$$308299b4.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])CGLIB$THREAD_CALLBACKS.get())[0];
    } 
  }
  
  static {
    CGLIB$STATICHOOK2();
    CGLIB$STATICHOOK1();
  }
  
  static void CGLIB$STATICHOOK2() {}
}

      @Configuration总结:

        在Spring的生命周期中,其中会beanFactory的后置处理器,执行时,先执行beanFactory的子接口BeanDefinitionRegistryPostProcessor,在这一步完成会包的扫描和类上面注解信息的解析,然后将普通类转换成beanDefinition对象,其中标注了@Configuration注解的类,会在beanDefinition中标记为full。然后再执行BeanFactoryPostProcessor的postProcessBeanFactory方法,在这一步会对beanDefinition中标记为full的进行cglib代理增强,使用cglib代理增强就意味着需要增强类不能使用final关键字修饰,在这个cglib代理增强类中是间接的实现BeanFactoryAware接口,这样就可以拿到BeanFactory,并且会创建一个public、BeanFactory类型名称为$$beanFactory进行接收BeanFactory, 并且cglib代理类会对方法进行拦截,这样就不用了每次都去new一个对象,所以使用@Configuration可以保证bean的单一性,并且,如果标注了@Bean注解的方法返回的对象是FactoryBean类型的,Spring会进行二次增强,确保是获取的bean是单一的。  

发布了227 篇原创文章 · 获赞 34 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_35634181/article/details/104550830