/**
* <pre>
*
* new AnnotationConfigApplicationContext(AppConfigDemo.class, ComponentE.class);
* 总结: AppConfigDemo,ComponentE都会作为Bean来对待,什么情况下会作为配置类来对待呢?
* 1. 类上存在@Configuration,@Component,@ComponentScan,@Import,@ImportResource
* 2. 如果不存在上面的注解,那么类中存在@Bean的方法也是作为一个配置类对待
* 3. 其他情况,它就是一个不同的@Bean
*
* </pre>
*/
class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
this.registriesPostProcessed.add(registryId);
// 处理配置类的BeanDefinition
processConfigBeanDefinitions(registry) {
// 配置类的BD
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
// 容器中所有的Bean的Name
String[] candidateNames = registry.getBeanDefinitionNames();
// 遍历所有beanName
for (String beanName : candidateNames) {
// 获取BD
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// 校验当前Bean是否符合配置类的条件
if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory) {
String className = beanDef.getBeanClassName();
// 如果没有类名,获取是@Bean方法,则不符合条件
if (className == null || beanDef.getFactoryMethodName() != null) {
return false;
}
// 如果类名相同,元数据相同,可以重用
AnnotationMetadata metadata;
if (beanDef instanceof AnnotatedBeanDefinition && className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
}
// 如果类型不相同,并且设置了Bean的Class
else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
// 获取Bean的class
Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
// 如果这个类又是BeanFactoryPostProcessor,BeanPostProcessor下面几种类型就不处理
// 不符合配置类的条件
if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
BeanPostProcessor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
EventListenerFactory.class.isAssignableFrom(beanClass)) {
return false;
}
// 创建当前类的元数据对象
metadata = AnnotationMetadata.introspect(beanClass) {
return new StandardAnnotationMetadata(introspectedClass, true);
}
}
// 其他条件,如果没有设置Bean的class,那么BD中存入的是类的全类名字符串
else {
// 获取元数据读取的工厂,根据类名解析该类的元数据
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
// 解析该类的元数据
metadata = metadataReader.getAnnotationMetadata();
}
// 以上的if就是获取类的元数据,说白了就是解析类的信息,例如类名,注解,等等信息
// 获取注解Configuration中的所有属性信息
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
// 如果存在表示有这个注解
// 获取proxyBeanMethods的值,如果是默认值true的话,表示@Bean方法需要被代理,因为@Bean的方法可以直接调用多次,返回的是同一个对象
// 所以必须要代理才能做到,如果是这种情况,则标记该类是个重量级的类
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
// 如果存在Configuration注解proxyBeanMethods为false的话,表示@Bean方法调用多次可以返回不同的对象,则无需代理
// 或者
else if (config != null || isConfigurationCandidate(metadata) {
// 如果此类是接口,不处理
if (metadata.isInterface()) {
return false;
}
// static {
// candidateIndicators.add(Component.class.getName());
// candidateIndicators.add(ComponentScan.class.getName());
// candidateIndicators.add(Import.class.getName());
// candidateIndicators.add(ImportResource.class.getName());
// }
// 如果是类上存在上面这几个注解,表示也属于配置Bean,也算作是一个配置类
for (String indicator : candidateIndicators) {
if (metadata.isAnnotated(indicator)) {
return true;
}
}
// 上面几种都没,判断当前类中是否存在@Bean标注的方法,如果存在,也表示是一个配置类
return metadata.hasAnnotatedMethods(Bean.class.getName());
}){
// 这种情况,标记当前类为轻量级的配置类
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
// 不存在标注为Bean的注解
else{
return false;
}
// 获取类上的Order注解
Integer order = getOrder(metadata) {
// 获取Order注解的属性
Map<String, Object> orderAttributes = metadata.getAnnotationAttributes(Order.class.getName());
return (orderAttributes != null ? ((Integer) orderAttributes.get(AnnotationUtils.VALUE)) : null);
}
// 如何存在Order注解,设置该Bean的Order值
if (order != null) {
beanDef.setAttribute(ORDER_ATTRIBUTE, order);
}
// 符合条件,不符合条件的上面已经返回false了
return true;
}){
// 保存该类为一个配置类
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// 如果没有找到@Configuration类,立即返回
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);
});
// 是否使用本地的BeanName生成器,也就是有没有指定的BeanNameGenerator
// localBeanNameGeneratorSet默认为false
if (!this.localBeanNameGeneratorSet) {
// 从容器中获取BeanNameGenerator
BeanNameGenerator generator = (BeanNameGenerator) registry.getSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
// 如果获取到了
if (generator != null) {
// 设置@ComponentScan扫描的类使用该BeanNameGenerator
this.componentScanBeanNameGenerator = generator;
// 设置@Import的类使用该BeanNameGenerator
this.importBeanNameGenerator = generator;
}
}
// 上下文环境对象
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// 创建Config类的解析器
ConfigurationClassParser parser = new ConfigurationClassParser(
// 用于解析类元数据的工厂
this.metadataReaderFactory,
// 解析时出现的问题报告
this.problemReporter,
// 环境对俩
this.environment,
// 加载类资源器
this.resourceLoader,
// 用于@ComponentScan扫描的类使用的BeanName生成器
this.componentScanBeanNameGenerator,
// Bean容器
registry);
// 符合条件的Bean
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
// 解析解析过的配置类
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
// 解析配置类,详见Spring中ConfigClass配置类是如何解析的
parser.parse(candidates);
// 校验解析的configClass,比如final的方法,静态方法,还有重写的方法,或者私有方法,抽象方法
parser.validate();
// 获取解析到的所有的配置类,封装成ConfigurationClass对象
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
// 删除已经解析过了的ConfigurationClass
configClasses.removeAll(alreadyParsed);
// 创建BeanDefinitionReader,它是将配置类中的配置统一进行成BeanDefinition的类
// 例如@Bean方法,@Import注解,说白了扫描的类都是由它来生成BeanDefinition
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry());
}
// 解析所有的配置属性,这个时候,BD就已经解析好了,详见BeanDefinitionReader的工作原理
this.reader.loadBeanDefinitions(configClasses);
// 保存已经解析的配置类
alreadyParsed.addAll(configClasses);
// 清空所有的配置类,因为都已经被解析过了
candidates.clear();
// 容器中现在存在的Bean与解析之前存在的@Bean的数量是不是发生了变化
// 如果大于,表示解析出来了新的Bean
// 那么我们就要对新解析的Bean进行再次解析
if (registry.getBeanDefinitionCount() > candidateNames.length) {
// 获取最新的所有的BeanName
String[] newCandidateNames = registry.getBeanDefinitionNames();
// 原始的所有BeanName
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
// 保存已经解析过的类
Set<String> alreadyParsedClasses = new HashSet<>();
// 遍历所有已经解析过的配置类
for (ConfigurationClass configurationClass : alreadyParsed) {
// 保存起来
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
// 遍历最新的所有BeanName
for (String candidateName : newCandidateNames) {
// 如果新解析出来的Bean没有被解析过
if (!oldCandidateNames.contains(candidateName)) {
// 获取BD
BeanDefinition bd = registry.getBeanDefinition(candidateName);
// 校验当前Bean是否符合配置类的条件,上面有这个方法的详解,并且该类没有被解析过
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && !alreadyParsedClasses.contains(bd.getBeanClassName())) {
// 保存新的需要解析的配置类
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
// 将这次最新的BeanName保存到candidateNames变量中
// candidateNames始终保存了上一次解析的所有BeanName
candidateNames = newCandidateNames;
}
}
// 当不断解析出来了新的Bean,那么就要一直解析,知道没有解析出新的Bean为止
while (!candidates.isEmpty());
// 如果不包含IMPORT_REGISTRY_BEAN_NAME,注入这个单例Bean
// 这个类是给解析@Import注解使用的,它保存了@Import导入的类
if (registry != null && !registry.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
registry.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
// 清空解析的类的一些元数据的缓存
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 在postProcessBeanDefinitionRegistry会执行processConfigBeanDefinitions
// 如果postProcessBeanDefinitionRegistry没有被执行,就需要执行一次
// 总之processConfigBeanDefinitions一定会被执行一次,用来解析所有配置类
if (!this.registriesPostProcessed.contains(factoryId)) {
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
// 给ConfigurationClass创建代理对象,因为@Bean方法的方法调用返回的是相同的Bean,所以需要给这个Config进行代理
enhanceConfigurationClasses(beanFactory){
// 配置类的BD
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
// 遍历所有的Bean
for (String beanName : beanFactory.getBeanDefinitionNames()) {
// 获取BD
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
// 获取代理类的标识
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) {
AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
// 不存在Class,表示存入的是类全名,将类全名解析为Class
if (!abd.hasBeanClass()) {
abd.resolveBeanClass(this.beanClassLoader);
}
}
// 如果该配置类设置了当前类是重量级类,表示需要使用代理完成@Bean方法多次调用返回同一个对象
// 并且,只有在@Configuration类中,才会设置为CONFIGURATION_CLASS_FULL
// 在@Component中是不会的,所以@Conmponent中的@Bean方法,每次调用都是返回一个新对象
if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
// 保存需要代理的配置类
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
// 如果没有解析到配置类,就不处理
if (configBeanDefs.isEmpty()) {
return;
}
// 创建CGLIB生成器
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
// 遍历所有的需要代理的配置类BD
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
// 如果@Configuration需要被代理,默认使用CGLIB代理
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// 获取Class类
Class<?> configClass = beanDef.getBeanClass();
// 生成ConfigClass的代理Class
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
// 使用代理的BeanClass代替原来的Class
beanDef.setBeanClass(enhancedClass);
}
}
}
// 添加一个处理实现了ImportAware导入的后置处理器,会将导入的配置类的元数据给它
// 所以,如果我们需要拿到导入的某一个类的元数据,就可以实现这个接口
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
}
Configuration注解ConfigurationClassPostProcessor运行原理
于 2024-02-24 21:15:48 首次发布