在spring 框架中开启某项功能,常常会在Application类中使用@EnableXXX注解,来开启某个功能。“开启”其实就是把相关的bean注入spring容器中。
以@EnableAsync为例。在@EnableAsync中使用@import把相关的bean注入容器中,这个bean默认是ProxyAsyncConfiguration。ProxyAsyncConfiguration是个@Configuration,导入AsyncAnnotationBeanPostProcessor,这是实际Async功能使用的bean。
再举一个例子,在spring中起到自动化配置的@EnableConfigurationProperties,也是通过@import注入 EnableConfigurationPropertiesRegistrar,通过后者扫描加载配置。
下面将说明@EnableAsync在spring底层的执行流程。通过这个例子,也能看到spring中最基础的功能 IOC和AOP 的底层执行过程。
先看一个常规的demo
(说明在前,代码在后)
1、 在ApiApplication上声明 @EnableAsync
@SpringBootApplication
@EnableConfigurationProperties
@EnableAsync //1
public class ApiApplication {
public static void main(String[] args) {
SpringApplication.run(ApiApplication.class, args);
}
}
2、在@EnableAsync里,使用@Import声明,通过AsyncConfigurationSelector导入需要的bean。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AsyncConfigurationSelector.class})//2
public @interface EnableAsync {
//省略
}
3、selectImports()返回要构造bean,spring会根据返回值实际去构造bean。 selector的意义就在于根据参数选择要装配的bean。
public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
//省略
@Nullable
public String[] selectImports(AdviceMode adviceMode) {
switch(adviceMode) {
case PROXY:
return new String[]{ProxyAsyncConfiguration.class.getName()};//3
case ASPECTJ:
return new String[]{"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration"};
//省略
}
}
以上是业务层看到的代码,但是看不到@EnableAsync什么时候被解析,selectImports什么时候被调用,bean怎么被构造和装配。
下面深入底层代码看执行流程
1、还是相同的入口
public class ApiApplication {
public static void main(String[] args) {
SpringApplication.run(ApiApplication.class, args);
}
}
2、调用SpringApplication的run方法。
public class SpringApplication {
public ConfigurableApplicationContext run(String... args) {
//省略
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
this.refreshContext(context);//2
this.afterRefresh(context, applicationArguments);
//省略
}
3、 调用SpringApplication的refresh方法。
protected void refresh(ConfigurableApplicationContext applicationContext) {
applicationContext.refresh();//3
}
}
4、调用AbstractApplicationContext的refresh。
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
public void refresh() throws BeansException, IllegalStateException {
//省略
this.prepareRefresh();
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory);//4
this.registerBeanPostProcessors(beanFactory);
//省略
}
}
5、调用PostProcessorRegistrationDelegate 的invokeBeanDefinitionRegistryPostProcessors方法。
final class PostProcessorRegistrationDelegate {
private static void invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
Iterator var2 = postProcessors.iterator();
while(var2.hasNext()) {
BeanDefinitionRegistryPostProcessor postProcessor = (BeanDefinitionRegistryPostProcessor)var2.next();
postProcessor.postProcessBeanDefinitionRegistry(registry);//5
}
}
}
中间部分调用代码省略。
7、调用ConfigurationClassParser类的parse()方法。这里beanName代表ApiApplication,metadata代表ApiApplication上所有的注解,包括@EnableAsync。
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
this.processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}
8、调用ConfigurationClassParser的doProcessConfigurationClass()方法。其中的getImports()方法,参数sourceClass是ApiApplication.class,这个方法扫描ApiApplication上所有的annotation,返回@import声明的bean名称列表。具体实现是以ApiApplication为root,递归的扫描过程所有的@注解。
protected final ConfigurationClassParser.SourceClass doProcessConfigurationClass(ConfigurationClass configClass, ConfigurationClassParser.SourceClass sourceClass, Predicate<String> filter) throws IOException {
this.processImports(configClass, sourceClass, this.getImports(sourceClass), filter, true);//8
}
9、调用ConfigurationClassParser的processImports方法,用来处理@import声明的bean。输入参数importCandidates是ApiApplication上@import声明的bean名称列表,包括AsyncConfigurationSelector。这个方法,逐个处理@import声明的bean,当处理到AsyncConfigurationSelector时,先通过构造器生成AsyncConfigurationSelector对象,然后调用Selector的selectImports方法,返回ProxyAsyncConfiguration类名。
10、此时importSourceClasses为ProxyAsyncConfiguration类名。继续递归processImports。
private void processImports(ConfigurationClass configClass, ConfigurationClassParser.SourceClass currentSourceClass, Collection<ConfigurationClassParser.SourceClass> importCandidates, Predicate<String> exclusionFilter, boolean checkForCircularImports) {
//省略
Iterator var6 = importCandidates.iterator();
while(var6.hasNext()) {
//省略
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());//9
Collection<ConfigurationClassParser.SourceClass> importSourceClasses = this.asSourceClasses(importClassNames, exclusionFilter);
this.processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);//10
}
//省略
11、如果importSourceClasses是Selector,将继续递归获得@import的bean。这里ProxyAsyncConfiguration是个普通的bean,所以直接构造bean。
12、与第8步相同,继续递归的检查ProxyAsyncConfiguration上的@import声明。
if (candidate.isAssignable(ImportSelector.class)) {
//省略
} else {
this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());//11
this.processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);//12
}
//省略
到此,ProxyAsyncConfiguration解析完成。下面创建ProxyAsyncConfiguration bean并初始化
1、前面的解析过程都是在1中执行,实际创建bean在2中。
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
public void refresh() throws BeansException, IllegalStateException {
//省略
this.prepareRefresh();
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory);//1
this.registerBeanPostProcessors(beanFactory);//2
//省略
}
}
2、在这个方法里创建bean
3、初始化bean,包括触发bean生成后的回调方法。ProxyAsyncConfiguration实现了ImportAware接口,这里触发setImportMetadata方法。
4、将生成的bean放入容器,也就是IOC的核心步骤。
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
instanceWrapper = this.createBeanInstance(beanName, mbd, args);//2
this.populateBean(beanName, mbd, instanceWrapper);//6
exposedObject = this.initializeBean(beanName, exposedObject, mbd);//3
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
this.autowireByName(beanName, mbd, bw, newPvs); //8
pvsToUse = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);//4
5、创建ProxyAsyncConfiguration对象。
6、其中delegate封装了CGLIB的构造器,实际生成proxyAsyncConfiguration对象。
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
beanInstance = this.getInstantiationStrategy().instantiate(mbd, beanName, this);
}//5
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
this.initBeanWrapper(bw);
return bw;
}
}
class DelegatingConstructorAccessorImpl extends ConstructorAccessorImpl {
private ConstructorAccessorImpl delegate;
public Object newInstance(Object[] var1) throws InstantiationException, IllegalArgumentException, InvocationTargetException {
return this.delegate.newInstance(var1);//6
}
}
7、ProxyAsyncConfiguration里定义了@Bean(AsyncAnnotationBeanPostProcessor),在构造的构成中也完成了AsyncAnnotationBeanPostProcessor的构造。
到此ProxyAsyncConfiguration bean的构造及初始化。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。