目录
一、继承关系
二、时序图
三、源码解析
postProcessBeanDefinitionRegistry()
2.1 获取到BeanDefinition列表,取出所有未解析过的BeanDefinition.
2.2 排序
2.3 解析bean
2.4 将读取到configClasses加载到容器中,即beanDefinitionMap
postProcessBeanFactory()
1. 对@Configuration标注的bean进行动态代理。
2. 添加一个后置处理器,用于给被cglib动态代理的bean注入BeanFactory
spring初始化过程中添加了很多spring自身创建的bean,其中最重要的就是ConfigurationClassPostProcessor,它完成了spring对于bean的扫描,以及配置类的代理。
可以看到ConfigurationClassPostProcessor实现的接口总共有三个源头:
1)Ordered ,这个接口的实现,是用来排序的
2)Aware 下的接口实现,主要是配置一些spring环境
3)BeanFactoryPostProcessor 这个接口就是ConfigurationClassPostProcessor的核心了,它完成了spring的扫描工作
前文已经介绍过BeanFactoryPostProcessor是一个工厂后置处理器,可以借助BeanFactory和BeanDefinitionRegistry(BeanDefinitionRegistryPostProcessor)完成一些操作
ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor接口,BeanDefinitionRegistryPostProcessor接口提供有两个方法,postProcessBeanDefinitionRegistry(BeanDefinitionRegistry)和postProcessBeanFactory(ConfigurableListableBeanFactory)。spring会先执行postProcessBeanDefinitionRegistry(),那么就先从postProcessBeanDefinitionRegistry()分析。
postProcessBeanDefinitionRegistry()方法传入了BeanDefinitionRegistry 即注册器,spring扫描完成就是借助BeanDefinitionRegistry。
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
//获取hash code
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
//执行bean 解析
processConfigBeanDefinitions(registry);
}
1. 获取一个registryId,添加到registriesPostProcessed中,这里只是做一个标记,标记该方法执行过。
2. 解析bean
List configCandidates = new ArrayList<>();
//从registry(factory)中获得所有BeanDefinitionNames
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//判断是否已经执行过,"full"和 "lite"都是标志
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
if (configCandidates.isEmpty()) {
return;
}
//这里会排序,根据Order
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
.....代码省略......
//创建ConfigurationClassParser,用于解析Bean
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set candidates = new LinkedHashSet<>(configCandidates);
Set alreadyParsed = new HashSet<>(configCandidates.size());
do {
//解析这个bean
parser.parse(candidates);
parser.validate();
Set configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
//创建一个reader
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
//将读取到configClasses加载到容器中,即beanDefinitionMap
this.reader.loadBeanDefinitions(configClasses);
//将configClasses加入到已经处理过的set中
alreadyParsed.addAll(configClasses);
candidates.clear();
.....代码省略......
}
while (!candidates.isEmpty());
.....代码省略......
判断是否有full或者lite标注,如果有,则证明已经解析过了
如果没有则未被解析,加入到集合configCandidates中
parser.parse(candidates)方法调用流程 :
//判断这个类有没有被别的@Import
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
return;
}
else {
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
// 处理配置类,由于配置类可能存在父类(若父类的全类名是以java开头的,则除外),所有需要将configClass变成sourceClass去解析,
// 然后返回sourceClass的父类。
// 如果此时父类为空,则不会进行while循环去解析,如果父类不为空,则会循环的去解析父类
// SourceClass的意义:简单的包装类,目的是为了以统一的方式去处理带有注解的类,不管这些类是如何加载的
// 如果无法理解,可以把它当做一个黑盒,不会影响看spring源码的主流程
SourceClass sourceClass = asSourceClass(configClass);
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
this.configurationClasses.put(configClass, configClass);
这里会将configClass处理成SourceClass,其实就是一个数据转存的过程。值得注意的是,最后那个do循环中会对继承关系进行处理。
它的核心代码是doProcessConfigurationClass(configClass, sourceClass)
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
//递归处理内部类
processMemberClasses(configClass, sourceClass);
}
// 处理 @PropertySource注解,注入的属性
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
//这里就是处理@ComponentScan扫描类了
//获取到@ComponentScan中属性的值
Set componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
//解析扫描包 最终委托给了componentScanParser去完成这件事
Set scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
//检查扫描的定义集是否有其他配置类,并在需要时递归解析
//就是扫描的包中如果有其他的配置类,那么就去解析这个配置类,并且查看是否定义了@ComponentScan注解
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
//这里是解析BeanDefinitionHolder,查看其中是否有配置类
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
//这里会再次去解析这个配置类
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
//处理 @Import注解
processImports(configClass, sourceClass, getImports(sourceClass), true);
//处理@ImportResource注解引入的配置文件
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
//处理 @Bean 方法
Set beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
//处理接口上的默认方法
processInterfaces(configClass, sourceClass);
//判断是否还有父类
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
return sourceClass.getSuperClass();
}
}
return null;
}
1)判断是否有内部类,有则递归调用处理内部类
2)处理 @PropertySource注解 这个属性注入
3)处理@ComponentScan
如果为空,说明此bean只是一个普通的bean,直接跳过该步骤
如果不为空,则说明该bean是一个配置类,读取出@ComponentScan 注解中的配置
委托给componentScanParser进行解析(放在下一篇中解析)
ConfigurationClassUtils.checkConfigurationClassCandidate()判断扫描出来的bean是否含有配置类。如有则递归解析
4)处理 @Import注解 (放在下一篇中解析)
5)处理@ImportResource注解引入的配置文件
6)处理 @Bean 方法
7)判断是否还有父类,如果有则返回,进行循环处理
public static boolean checkConfigurationClassCandidate(
BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
//.....省略部分代码
/**
* 判断是否加了@Configuration注解,添加了@Configuration注解的bean会被添加一个full标记,
* 会在ConfigurationClassPostProcessor#postProcessBeanFactory()中被使用cglib动态代理增强,通过cglib动态代理实现
* 使用@Configuration注解的bean中的 @Bean方法只会被调用一次(包含直接调用@Bean方法),即单例。
* @see ConfigurationClassPostProcessor#postProcessBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory)
* @reviewer wangcongming
*/
if (isFullConfigurationCandidate(metadata)) {
//如果加了@Configuration注解,则给beanDef加一个full标识
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
else if (isLiteConfigurationCandidate(metadata)) {
//给beanDef加一个lite标识
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}
//.....省略部分代码
}
public static boolean isLiteConfigurationCandidate(AnnotationMetadata metadata) {
//1. 判断是否是接口
if (metadata.isInterface()) {
return false;
}
/**
* 2. 判断是否加了以下注解
* Component ComponentScan Import ImportResource
* @reviewer wangcongming
*/
for (String indicator : candidateIndicators) {
if (metadata.isAnnotated(indicator)) {
return true;
}
}
// 3. 查找加了@bean注解的方法
try {
return metadata.hasAnnotatedMethods(Bean.class.getName());
}
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
}
return false;
}
}
这段源码可以看出以下几点:
1)被@Configuration标记的bean,会被标记为“full”,被@Component、@ComponentScan、@Import、@ImportResource标记的则会被标记为“lite” ,如果没有加以上注解,则会直接跳过该bean
2)@Import @ComponentScan @ImportResource或者类中有@Bean的方法的bean,没有使用@Configuration注解,也会被spring解析
this.reader.loadBeanDefinitions(configClasses);
这一行代码就是将@Import导入的bean加载为BeanDefinition(具体解析放在下一篇)
在这里postProcessBeanFactory()方法主要是对@Configuration标注的bean进行代理。
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//......省略部分代码
/**
* 对@Configuration标注的类中的@Bean方法进行cglib动态代理
* 为什么要动态代理呢?
* spring中的bean未被标注时,应该都是单例的,但是如果直接调用@Bean的方法创建对象,就会出现多例,与实际情况不符
* 此时可以采用动态代理来解决
* @reviewer wangcongming
*/
enhanceConfigurationClasses(beanFactory);
//这里会添加一个后置处理器,用于给被cglib动态代理的bean注入BeanFactory
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
//将使用full标记的BeanDefinition存入configBeanDefs
Map configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
//是否使用full标记
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
//......省略部分代码
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
//......省略部分代码
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
try {
Class> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
if (configClass != null) {
//调用ConfigurationClassEnhancer.enhance()方法创建增强类 这时返回的class是经过cglib动态代理后的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()));
}
beanDef.setBeanClass(enhancedClass);
}
}
}
catch (Throwable ex) {
throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
}
Class> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);这里就是生成代理对象。
这里使用的是cglib动态代理,为什么不使用jdk动态代理,这是因为jdk动态代理是基于接口的
private Enhancer newEnhancer(Class> configSuperClass, @Nullable ClassLoader classLoader) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(configSuperClass);
//给新创建的代理对象添加一个接口EnhancedConfiguration
/**
* @see ConfigurationClassPostProcessor.ImportAwareBeanPostProcessor
*/
enhancer.setInterfaces(new Class>[] {EnhancedConfiguration.class});
enhancer.setUseFactory(false);
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
//设置生成代理class的策略
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
/**
* 添加了两个MethodInterceptor。(BeanMethodInterceptor和BeanFactoryAwareMethodInterceptor)
* 通过这两个类的名称,可以猜出,前者是对加了@Bean注解的方法进行增强,后者是为代理对象的beanFactory属性进行增强
* 被代理的对象,如何对方法进行增强呢?就是通过MethodInterceptor拦截器实现的
* 类似于拦截器,每次执行请求时,都会对经过拦截器。
* 同样,加了MethodInterceptor,那么在每次代理对象的方法时,都会先经过MethodInterceptor中的方法
* @reviewer wangcongming
*/
enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer;
}
1)给代理类设置一个接口EnhancedConfiguration
添加EnhancedConfiguration接口,是因为会set一个BeanFactory,通过BeanFactory可以取出已经实例化的bean。
2)设置代理class生成策略
3)添加CallbackFilter
private static final Callback[] CALLBACKS = new Callback[] {
new BeanMethodInterceptor(),
new BeanFactoryAwareMethodInterceptor(),
NoOp.INSTANCE
};
可以看出这里是添加了两个Callback
BeanMethodInterceptor,功能是判断@Bean标注的方法创建的对象是否已经添加到BeanFactory中,如果有则直接取出返回,没有则创建。这就保证了Bean示例的单例性
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
MethodProxy cglibMethodProxy) throws Throwable {
//......省略部分代码
//这里就是查看beanFactory中是否有该@Bean方法创建的对象,如果有则直接返回,没有则创建
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 {
return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
}
}
if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
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);
}
BeanFactoryAwareMethodInterceptor 功能是给代理对象添加一个BeanFactory属性
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
众所周知,后置处理器会在bean初始化完成之后调用,调用ImportAwareBeanPostProcessor后置处理器,会给被cglib动态代理的配置类注入一个BeanFactory(通过EnhancedConfiguration接口的setBeanFactory()注入)。