spring源码(四)——@Configuration到底干了什么

前言

上篇博客基本梳理了一下@Configuration注解的类注册源码上的一些细节和流程。

一个实例

准备三个类,一个配置类,两个普通类,其中一个普通类可以什么都不做

@Component
public class TestBean {
    //这个普通类里面只有一个构造方法
    public TestBean() {
        System.out.println("this is testBean one constructor method");
    }
}
/**
 * autor:liman
 * createtime:2020/4/6
 * comment:
 */
public class TestBean02 {

}

配置类

@Configuration
@ComponentScan(value="com.learn.importselector.config")
public class AppConfig {
    
    @Bean
    public TestBean testBean(){
        return new TestBean();
    }
    
    @Bean
    public TestBean02 testBean02(){
        testBean();//这里也会调用testBean方法。
        return new TestBean02();
    }
}

问题:TestBean的构造方法会被调用几次?注意在TestBean02中也会调用testBean方法。

引入一个测试代码

public class TestOutOfConfig {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext
                = new AnnotationConfigApplicationContext(AppConfig.class);

        TestBean02 testBean = annotationConfigApplicationContext.getBean(TestBean02.class);
    }
}

答案:如果加上了@Configuration,则只会调用一次,如果去掉@Configuration注解则会调用两次

运行情况:

加入了@Configuration注解后的运行情况

在这里插入图片描述

取消@Configuration注解后的运行情况

在这里插入图片描述

问题:@Configuration到底干了啥?为啥去掉@Configuration之后会调用两次?

CGLIB代理的简单实例

其实之前总结过代理,这里还是想说一下CGLIB的代理,因为后面的源码阅读会用到

一个目标类

/**
 * autor:liman
 * createtime:2020/4/11
 * comment:
 */
public class HelloService {
	public HelloService(){
		System.out.println("this is construct method of HelloService");
	}
    //这个方法不会被代理,因为是final方法
	final public String sayOthers(String name){
		System.out.println("hello service to others : "+name);
		return null;
	}
	public void sayHello(){
		System.out.println("helloService:sayHello");
	}
}

一个方法调用拦截器

public class SelfMethodInterceptor implements MethodInterceptor {

	/**
	 *
	 * @param o 目标对象
	 * @param method 目标方法
	 * @param objects 目标方法参数
	 * @param methodProxy 目标方法的代理类 methodProxy.invokeSuper()
	 * @return
	 * @throws Throwable
	 */
	@Override
	public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
		System.out.println("self interceptor before");
		System.out.println(method.getName());//sayHello()
		methodProxy.invokeSuper(o,objects);
		System.out.println(methodProxy.getClass().getSimpleName());
		System.out.println(methodProxy.getSignature());//代理后的方法
		System.out.println("self interceptor after");
		return null;
	}
}

调用的实例

/**
 * autor:liman
 * createtime:2020/4/11
 * comment:这里需要引入CGLIB的调用包
 */
public class CglibTest {

	public static void main(String[] args) {
//将生成的代理类导入到指定文件夹,可以查看CGLIB生成的代理类的class源码
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"E:\\cglib_class");
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(HelloService.class);
		enhancer.setCallback(new SelfMethodInterceptor());
		HelloService proxy = (HelloService) enhancer.create();
		proxy.sayHello();
	}

}

依旧是个前提

我们这篇博客是要总结@Configuration这个注解spring底层到底干了什么,这里我们就从上篇博客的后续开始,还是贴入我们讨论了很多次的方法

//TODO :PostProcessorRegistrationDelegate中的第56行
public static void invokeBeanFactoryPostProcessors(
		ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

	// Invoke BeanDefinitionRegistryPostProcessors first, if any.
    //TODO: 定义一个容器,表示已经处理过了的BeanFactoryPostProcessor
	Set<String> processedBeans = new HashSet<>();

	//TODO:如果BeanFactory是一个注册器(这个好像必会进入)
	if (beanFactory instanceof BeanDefinitionRegistry) {
		BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;

		//TODO:这里定义了两个集合,一个是BeanFactoryPostProcessor,一个是BeanDefinitionRegistryPostProcessor
		//TODO:放自定义的BeanFactoryPostProcessor
		List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
		//TODO:BeanDefinitionRegistryPostProcessor只是继承了BeanFactoryPostProcessor接口而已
		//TODO:放自定义的BeanDefinitionRegistryPostProcessor
		List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

		//TODO : 遍历传入过来的集合beanFactoryPostProcessors
		for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
			//TODO:如果自定义的BeanFactoryPostProcessor实现了BeanDefinitionRegistryPostProcessor接口
			if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {//TODO:如果是BeanDefinitionRegistryPostProcessor
				BeanDefinitionRegistryPostProcessor registryProcessor =
						(BeanDefinitionRegistryPostProcessor) postProcessor;
				registryProcessor.postProcessBeanDefinitionRegistry(registry);//TODO:调用postProcessor其中的方法
				registryProcessors.add(registryProcessor);
			}
			else {//TODO:如果自定义的BeanFactoryPostProcessor没有实现现BeanDefinitionRegistryPostProcessor接口
				regularPostProcessors.add(postProcessor); //TODO:将自定义的BeanFactoryProcessor放到上面定义的集合中
			}
		}

		// Do not initialize FactoryBeans here: We need to leave all regular beans
		// uninitialized to let the bean factory post-processors apply to them!
		// Separate between BeanDefinitionRegistryPostProcessors that implement
		// PriorityOrdered, Ordered, and the rest.
		//TODO:又定义一个集合存放BeanDefinitionRegistryPostProcessor,这个集合存放的是spring内部实现了这个接口的类
		//TODO:放spring内部定义的BeanDefinitionRegistryPostProcessor
		//TODO:每次真正调用的,才是这个集合中的BeanDefinitionRegistryPostProcessor
		List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

		// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
		//TODO:根据bean的类型获取bean的名称,这里获取的是BeanDefinitionRegistryPostProcessor类型的
		//TODO:首先调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
		//TODO:根据Type获取对应类型的beanName,这里才会获取出内部定义的ConfigurationClassPostProcessor
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
		//TODO:遍历上面获得的postProcessorNames,并根据每个beanName获取对应的beanDefinition,然后放到currentRegistryProcessors中
		//TODO:如果没有自定义的,则这个时候这里就一个
		//TODO:同时将遍历的每一个beanName放到processedBeans中
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				//TODO:将 ConfigurationClassPostProcessor 标记为已经处理
				processedBeans.add(ppName);
			}
		}
		//TODO:设置排序,不重要
		sortPostProcessors(currentRegistryProcessors, beanFactory);
		//TODO:合并两个集合,将spring自定义的Processors加入到registryProcessors中,可以看到所谓的currentRegistryProcessors就是一个过渡的
		registryProcessors.addAll(currentRegistryProcessors);
		//TODO:真正的开始调用BeanDefinitionRegistryPostProcessor中的方法
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
		//TODO:清空currentRegistryProcessors,这里就清除了 ConfigurationClassPostProcessor
		currentRegistryProcessors.clear();

		// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
		//TODO:开始调用实现了Ordered接口的BeanDefinitionRegistryPostProcessor类
		postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
		for (String ppName : postProcessorNames) {
			if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				processedBeans.add(ppName);
			}
		}
		//TODO:和上面的操作一样,但是这个时候 currentRegistryProcessors 中只会有实现了Ordered接口的BeanDefinitionRegistryPostProcessor
		sortPostProcessors(currentRegistryProcessors, beanFactory);
		registryProcessors.addAll(currentRegistryProcessors);
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
		currentRegistryProcessors.clear();

		// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
		//TODO:最后,调用其他的BeanDefinitionRegistryPostProcessors,直到没有更多的BeanDefinitionRegistryPostProcessors实现类
		//TODO:简单点说这里就是在扫除剩余的没被调用的BeanDefinitionRegistryPostProcessors实例
		boolean reiterate = true;
		while (reiterate) {
			reiterate = false;
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
					reiterate = true;
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();
		}

		// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
		//TODO:到这里,调用postProcessBeanFactory(即BeanDefinitionRegistryPostProcessors的父类)的回调方法,这里面就有针对@Configuration类的增强操作
		invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
	}

	//TODO:如果一个beanFactory不是注册器,这个应该是一个兼容操作,老版本的spring的BeanFactory是没有实现Registry接口的
	else {
		// Invoke factory processors registered with the context instance.
		invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
	}

	//TODO:开始处理 BeanFactoryProcessor 类型的类,并回调指定的方法(就是只实现了BeanFactoryPorcessor接口的类)
	// Do not initialize FactoryBeans here: We need to leave all regular beans
	// uninitialized to let the bean factory post-processors apply to them!
	String[] postProcessorNames =
			beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

	// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
	// Ordered, and the rest.
	//TODO:如果已经在processedBeans集合中,这里不再做处理
	List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();//TODO:存放实现了 PriorityOrdered 接口的 BeanFactoryProcessor
	List<String> orderedPostProcessorNames = new ArrayList<>(); //TODO:存放实现了 Ordered 接口的 BeanFactoryProcessor
	List<String> nonOrderedPostProcessorNames = new ArrayList<>();//TODO:存放没有实现 Ordered 接口也没有实现 PriorityOrdered 的 BeanFactoryProcessor
	for (String ppName : postProcessorNames) {
		if (processedBeans.contains(ppName)) {
			// skip - already processed in first phase above
		}
		else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
			priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
		}
		else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
			orderedPostProcessorNames.add(ppName);
		}
		else {
			nonOrderedPostProcessorNames.add(ppName);
		}
	}

	//TODO:调用实现了PriorityOrdered接口的BeanFactoryPostProcessor回调方法
	// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

	//TODO:调用实现了Ordered接口的 BeanFactoryPostProcessors 回调方法
	// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
	List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
	for (String postProcessorName : orderedPostProcessorNames) {
		orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
	}
	sortPostProcessors(orderedPostProcessors, beanFactory);
	invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

	// Finally, invoke all other BeanFactoryPostProcessors.
	//TODO:最后,处理两个接口为没有实现的正常的 BeanFactoryPostProcessors 回调方法
	List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
	for (String postProcessorName : nonOrderedPostProcessorNames) {
		nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
	}
	invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

	// Clear cached merged bean definitions since the post-processors might have
	// modified the original metadata, e.g. replacing placeholders in values...
	beanFactory.clearMetadataCache();
}

这里再次总结一下spring中回调BeanFactoryPostProcessor接口实现类的方法,就是上面这段代码,invokeBeanFactoryPostProcessors方法。

这个方法在AbstractApplicationContext类中被调用的时候,传入进来的是这样的

//TODO:通过委托对象调用指定的BeanFactoryPostProcessor(这里是调用自定义的BeanFactoryPostProcessor)
//TODO:这里的getBeanFactoryPostProcessors()并不是取出spring内部定义的BeanFactoryPostProcessor,而是取出程序员自己定义的BeanFactoryPostProcessor
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

这里只需记住一点,通过getBeanFactoryPostProcessors()得到的是我们自己定义的BeanFactoryPostProcessor 。前面我们说过,BeanFactoryPostProcessor其实还有一个子接口BeanDefinitionRegistryPostProcessor源码如下所示

/**
 * Extension to the standard {@link BeanFactoryPostProcessor} SPI, allowing for
 * the registration of further bean definitions <i>before</i> regular
 * BeanFactoryPostProcessor detection kicks in. In particular,
 * BeanDefinitionRegistryPostProcessor may register further bean definitions
 * which in turn define BeanFactoryPostProcessor instances.
 *
 * @author Juergen Hoeller
 * @since 3.0.1
 * @see org.springframework.context.annotation.ConfigurationClassPostProcessor
 */
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

	/**
	 * Modify the application context's internal bean definition registry after its
	 * standard initialization. All regular bean definitions will have been loaded,
	 * but no beans will have been instantiated yet. This allows for adding further
	 * bean definitions before the next post-processing phase kicks in.
	 * @param registry the bean definition registry used by the application context
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

接口BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor的基础上扩展了一个方法。这也就意味着BeanDefinitionRegistryPostProcessor接口有两个方法。我们看看spring是怎么处理的(其实关于spring如何调用BeanFactoryPostProcessor后置处理的,在上面整个方法的代码中,已经通过注解给出了)。下面一段段解构上述方法。首先说明一下,在invokeBeanFactoryPostProcessors方法中,spring为了兼容原来老版本的操作,做了一个if判断,判断如果BeanFactory是BeanDefinitionRegistry的话就进入一个if语句块,如果不是,就走else分支。这里我们从if语句块开始。

1、先处理自定义的BeanFactoryPostProcessor

//TODO:如果BeanFactory是一个注册器(这个好像必会进入)
if (beanFactory instanceof BeanDefinitionRegistry) {
	BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;

	//TODO:这里定义了两个集合,一个是BeanFactoryPostProcessor,一个是BeanDefinitionRegistryPostProcessor
	//TODO:放自定义的BeanFactoryPostProcessor
	List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
	//TODO:BeanDefinitionRegistryPostProcessor只是继承了BeanFactoryPostProcessor接口而已
	//TODO:放自定义的BeanDefinitionRegistryPostProcessor
	List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

	//TODO : 遍历传入过来的集合beanFactoryPostProcessors
	for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
		//TODO:如果自定义的BeanFactoryPostProcessor实现了BeanDefinitionRegistryPostProcessor接口
		if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {//TODO:如果是BeanDefinitionRegistryPostProcessor
			BeanDefinitionRegistryPostProcessor registryProcessor =
					(BeanDefinitionRegistryPostProcessor) postProcessor;
			registryProcessor.postProcessBeanDefinitionRegistry(registry);//TODO:调用postProcessor其中的方法
			registryProcessors.add(registryProcessor);
		}
		else {//TODO:如果自定义的BeanFactoryPostProcessor没有实现现BeanDefinitionRegistryPostProcessor接口
			regularPostProcessors.add(postProcessor); //TODO:将自定义的BeanFactoryProcessor放到上面定义的集合中
		}
	}
	
	//............暂时省略后面的代码
}

我们说过,通过参数传递进来的beanFactoryPostProcessors是我们自己定义的beanFactoryPostProcessors,可以很明显的看到,如果我们定义的beanFactoryPostProcessors实现了BeanDefinitionRegistryPostProcessor接口,则会被先处理,然后放入registryProcessors集合中,如果只实现了BeanFactoryPostProcessor接口,则会放入regularPostProcessors集合中

2、开始处理spring内部实现了BeanDefinitionRegistryPostProcessor接口的实现类。

之后我们接着往下看

// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
//TODO:又定义一个集合存放BeanDefinitionRegistryPostProcessor,这个集合存放的是spring内部实现了这个接口的类
//TODO:放spring内部定义的BeanDefinitionRegistryPostProcessor
//TODO:每次真正调用的,才是这个集合中的BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
//TODO:根据bean的类型获取bean的名称,这里获取的是BeanDefinitionRegistryPostProcessor类型的
//TODO:首先调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
//TODO:根据Type获取对应类型的beanName,这里才会获取出内部定义的ConfigurationClassPostProcessor
String[] postProcessorNames =
		beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
//TODO:遍历上面获得的postProcessorNames,并根据每个beanName获取对应的beanDefinition,然后放到currentRegistryProcessors中
//TODO:如果没有自定义的,则这个时候这里就一个
//TODO:同时将遍历的每一个beanName放到processedBeans中
for (String ppName : postProcessorNames) {
	if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
		currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
		//TODO:将 ConfigurationClassPostProcessor 标记为已经处理
		processedBeans.add(ppName);
	}
}
//TODO:设置排序,不重要
sortPostProcessors(currentRegistryProcessors, beanFactory);
//TODO:合并两个集合,将spring自定义的Processors加入到registryProcessors中,可以看到所谓的currentRegistryProcessors就是一个过渡的
registryProcessors.addAll(currentRegistryProcessors);
//TODO:真正的开始调用BeanDefinitionRegistryPostProcessor中的方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//TODO:清空currentRegistryProcessors,这里就清除了 ConfigurationClassPostProcessor
currentRegistryProcessors.clear();

我们发现又定义了一个currentRegistryProcessors集合,这个集合其实就是用来存放待处理的BeanFactoryPostProcessor实现类。

通过如下这一句,spring获得了内部自动创建的,并且实现了BeanDefinitionRegistryPostProcessor接口的实现类。之前我们讨论过,在spring初始化过程中,会为我们自动创建六个重要的对象,这六个重要的对象中,有一个就实现了这个接口,这个就是ConfigurationClassPostProcessor

String[] postProcessorNames =
		beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

通过这一句代码,spring就获取了创建的ConfigurationClassPostProcessor对象。

我们可以看到处理的代码很简单,只是将这个对象放入currentRegistryProcessors集合中,并在invokeBeanDefinitionRegistryPostProcessors执行之后,就清空了currentRegistryProcessors集合,其中invokeBeanDefinitionRegistryPostProcessors底部就是完成ConfigurationClassPostProcessor对象中postProcessBeanDefinitionRegistry方法的回调,这个方法中就完成了包的扫描和beanDefinition的注册。

3、之后,调用实现了Ordered接口的BeanDefinitionRegistryPostProcessor和还没有被调用的BeanDefinitionRegistryPostProcessor对象。这个不太重要,但是套路都是一个

// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
//TODO:开始调用实现了Ordered接口的 BeanDefinitionRegistryPostProcessor 类
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
	if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
		currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
		processedBeans.add(ppName);
	}
}
//TODO:和上面的操作一样,但是这个时候 currentRegistryProcessors 中只会有实现了Ordered接口的BeanDefinitionRegistryPostProcessor
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();

// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
//TODO:最后,调用其他的BeanDefinitionRegistryPostProcessors,直到没有更多的BeanDefinitionRegistryPostProcessors实现类
//TODO:简单点说这里就是在扫除剩余的没被调用的BeanDefinitionRegistryPostProcessors实例
boolean reiterate = true;
while (reiterate) {
	reiterate = false;
	postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
	for (String ppName : postProcessorNames) {
		if (!processedBeans.contains(ppName)) {
			currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
			processedBeans.add(ppName);
			reiterate = true;
		}
	}
	sortPostProcessors(currentRegistryProcessors, beanFactory);
	registryProcessors.addAll(currentRegistryProcessors);
	invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
	currentRegistryProcessors.clear();
}

4、之后回调BeanFactoryPostProcessor对象中的postProcessBeanFactory方法

// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
//TODO:到这里,调用postProcessBeanFactory(即BeanDefinitionRegistryPostProcessors的父类)的回调方法,这里面就有针对@Configuration类的增强操作
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

后面的代码大同小异,只是针对spring框架中内部实现了BeanFactoryPostProcessor接口的类,整个方法梳理到这里,我们至少可以得出一个结论。在这个比较复杂的方法中,spring是先处理的BeanDefinitionRegistryPostProcessor的回调,再处理的BeanFactoryPostProcessor的回调(或者你会说废话)但是接下来的东西就比较重要了,我们说过spring内部定义的一个类ConfigurationClassPostProcessor即实现了BeanDefinitionRegistryPostProcessor接口,也实现了BeanFactoryPostProcessor接口,那么根据我们刚才得出的结论,我们就可以得出,spring是先回调ConfigurationClassPostProcessor类中的postProcessBeanDefinitionRegistry方法,再回调ConfigurationClassPostProcessor类中的postProcessBeanFactory方法。

上一篇博客中,我们详细介绍了spring回调ConfigurationClassPostProcessor类中的postProcessBeanDefinitionRegistry方法的操作,spring就是在这个方法底层完成了扫描和@Import注解的处理,同时也标记出了@Configuration类,这个方法的回调工作就完成了。但是我们开头说了,针对@Configuration标记的类,可不简单的标记扫描注册就完事,至少还要有个代理。至少要避免我们开头那种操作(调用两次实例化方法的操作)

@Configuration的面纱

从 ConfigurationClassPostProcessor 回调postProcessBeanFactory方法说起。

/**
 * TODO:ConfigurationClassPostProcessor第243行
 * TODO:这里会完成对@Configuration的增强处理
 * 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);
	}

	//TODO:对@Configuration实现增强处理
	enhanceConfigurationClasses(beanFactory);
	beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

于是我们发现有个enhanceConfigurationClasses的方法,enhance就是增强的意思。说明spring底层对@Configuration标记的类进行了一个增强。继续进入

/**
 * TODO:onfigurationClassPostProcessor 第338行
 * TODO:对@Configuration进行增强处理
 * 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);
		//TODO://是否是一个全代理的类(是否加了@Configuration)
		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");
			}
			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'.");
			}
			//TODO:如果加了@Configuration 则放入configBeanDefs集合中
			configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
		}
	}
	if (configBeanDefs.isEmpty()) {
		// nothing to enhance -> return immediately
		return;
	}

	//TODO:对@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
		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) {
				//TODO:进行增强
				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()));
					}
					beanDef.setBeanClass(enhancedClass);
				}
			}
		}
		catch (Throwable ex) {
			throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
		}
	}
}

可以看到这个方法比较简单,也就是遍历了BeanDefinition的名字,然后通过名字取出指定的BeanDefinition ,判断这个BeanDefinition是否是@Configuration标记的类,如果是则放入configBeanDefs集合中。之后遍历这个集合对每一个@Configuration进行代理操作。所以核心就是下面这一行

Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);

继续往下

/**
 * TODO:ConfigurationClassEnhancer中的第97行
 * Loads the specified class and generates a CGLIB subclass of it equipped with
 * container-aware callbacks capable of respecting scoping and other bean semantics.
 * @return the enhanced subclass
 */
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;
	}
	//TODO:利用CGLIB创建增强类,newEnhancer完成具体的增强属性的设置
	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;
}

通过spring本身的英文注释就能看出,这是一个通过CGLIB生成代理子类的方法(这也就是我为啥要在开头列出一个CGLIB的实例的原因),如果不熟悉CGLIB的就看文章开头的那个实例。

之后进入到createClass中的newEnhancer方法中

/**
 * TODO:ConfigurationClassEnhancer第122行
 * TODO:创建一个基于CGLIB的增强类
 * Creates a new CGLIB {@link Enhancer} instance.
 */
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
	Enhancer enhancer = new Enhancer();
	//TODO:将当前配置了设置成父类
	enhancer.setSuperclass(configSuperClass);
	//TODO:让代理类实现EnhancedConfiguration接口,这个接口继承了BeanFactoryAware接口,可让我们的代理类获得BeanFactory便于重新注册相关bean
	enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
	enhancer.setUseFactory(false);//TODO:代理类的产生不利用工厂模式
	//TODO:命名策略
	enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
	//TODO:设置CGLIB的生成策略
	enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
	//TODO:设置最终代理类的回调拦截器
	enhancer.setCallbackFilter(CALLBACK_FILTER);
	enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
	//TODO:返回生成的代理类
	return enhancer;
}

文章开头的那个实例中说过,CGLIB的代理的增强逻辑主要就在拦截器中,我们看到, enhancer.setCallbackFilter(CALLBACK_FILTER);这个不就是设置代理的逻辑么,继续进入

// The callbacks to use. Note that these callbacks must be stateless.
private static final Callback[] CALLBACKS = new Callback[] {
		new BeanMethodInterceptor(),
		new BeanFactoryAwareMethodInterceptor(),
		NoOp.INSTANCE
};

private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);

发现给@Configuration标记的类主要的代理逻辑就在BeanMethodInterceptorBeanFactoryAwareMethodInterceptor中重点看这两个类中的intercept方法即可

BeanMethodInterceptor

这个主要就是针对调用@Configuration标记的类中的@Bean方法的拦截操作

/**
 * TODO:针对@Bean方法的增强
 * Enhance a {@link Bean @Bean} method to check the supplied BeanFactory for the
 * existence of this bean object.
 * @throws Throwable as a catch-all for any exception that may be thrown when invoking the
 * super implementation of the proxied method i.e., the actual {@code @Bean} method
 */
@Override
@Nullable
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
			MethodProxy cglibMethodProxy) throws Throwable {

	//TODO:获取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;
		}
	}

	// 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.
	//TODO:处理@Bean方法返回FactroyBean的情况
	/**
	 * TODO:首先,检查@Bean方法返回的是否是一个FactoryBean,如果是,则创建一个返回的FactoryBean的代理类
	 * TODO:底层调用FactoryBean中的getObject方法,然后返回这个对象。
	 */
	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 {
			//TODO:针对BeanFactory的增强操作,并调用getObject方法
			// It is a candidate FactoryBean - go ahead with enhancement
			return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
		}
	}

    //TODO:针对普通的bean的处理
	//TODO:为了避免出现嵌套调用的问题 isCurrentlyInvokedFactoryMethod
	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.
		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()));
		}
		//TODO:调用@Configuration类中的目标方法
		return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
	}

	return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}

整体来看这个方法分为三个分支,针对web操作中,@Bean注解的方法返回的bean是否是一个域级的代理;@Bean注解的方法返回的bean是否是一个FactoryBean;以及@Bean注解的方法返回的bean是一个普通的bean,如何避免被重复调用的问题,都有处理

其中isCurrentlyInvokedFactoryMethod这个判断方法就是为了避免我们开头实例中两次执行的情况。

BeanFactoryAwareMethodInterceptor

这个是针对如果这个配置类实现了BeanFactoryAware接口的拦截操作

@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");
	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;
}

这个方法就简单的多。只是一个简单的判断,之后直接调用

总结

整篇博客预热较久,但是针对@Configuration与@ComponentScan和@Import等注解有何区别,这里似乎可以有个结论了:@Configuration标记的类在spring中会被将对应的BeanDefinition属性configurationClass标记为FULL,而其他的则会将BeanDefinition属性configurationClass标记为lite(中文为:部分)。另一个最大的区别就是加上了@Configuration注解的类,spring底层会用CGLIB对这个类做一个代理,而其他注解则不会。这就是@Configuration最特殊的地方,也是最牛逼的地方。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章