本文涉及主题

1. BeanFactoryPostProcessor调用过程源码剖析

2. 配置类的解析过程源码

3. 配置类@Configuration加与不加的区别

4. 重复beanName的覆盖规则

5. @ComponentScan的解析原理


一. 研究目标: 解析spring如何加载配置类

我们经常会在一个类上打上@Configuration, @Component, @Bean等. 带有这些注解的类, 就是我们所说的配置类. 那么, spring启动的时候,是如何加载这些配置类的呢?

下面就以此为目的, 分析spring源码. 本节的内容是对上一节内容的实战分析, 同时更加详细的解读spring源码

我们知道, spring启动的时候做了3件事, 就是上面的三件事.

第一件事: 调用this()自身的无参构造函数. 初始化了BeanDefinitionReader和BeanDefinitionScanner, 同时初始化了很多spring的原始后置处理器, 这些处理器是用来加载bean的

第二件事: 调用register(..) 注册配置类

第三件事: refresh(..) 这里包含了整个ioc创建bean的全生命周期, 今天重点看invokeBeanFactoryPostProcessors(beanFactory)加载配置类

二. 准备工作: 自定义配置类MainConfig

我们先定义好要分析加载的配置类

package com.lxl.www.iocbeanlifecicle;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; /**
* 这是一个配置类,
* 在配置类里面定义了扫描的包路径com.lxl.www.iocbeanlifecicle
* 这是会将这个包下配置了注解的类扫描到ioc容器里面,成为一个成熟的bean
*/
@Configuration
@ComponentScan(basePackages = {"com.lxl.www.iocbeanlifecicle"})
public class MainConfig {
}

这个配置类很简单, 使用@ComponentScan注解指定了扫描的包. @Configuration指定当前是一个配置类

接下来定义一个main方法, 加载配置类.

 package com.lxl.www.iocbeanlifecicle;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MainStarter {
public static void main(String[] args) {
// 第一步: 通过AnnotationConfigApplicationContext读取一个配置类
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
//context.addBeanFactoryPostProcessor();
Car car = (Car) context.getBean("car");
System.out.println(car.getName());
context.close();
}
}

在main里, 通过AnnotationConfigurationApplicationContext读取配置类MainConfig.class.

配置类被传进来以后, 到底是怎么被解析的呢? 这就是我们分析的线索

始终不要忘记我们的整体架构图. 对照这个图来分析. 思路更清晰. 整体内容讲解在这里: https://www.cnblogs.com/ITPower/p/13677635.html

下面, 从入口进入. 我们的入口就是这里

new AnnotationConfigApplicationContext(MainConfig.class);

下面进入AnnotationConfigApplicationContext的构造方法

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
// 进入构造函数, 首先调用自身的构造方法this();
// 调用自身的构造方法之前, 要先调用父类的构造方法
this();
// register配置注册类
register(componentClasses);
// ioc容器shua新接口--非常重要
refresh();
}

三、读取配置类后置处理器ConfigurationClassPostProcessor

3.1 调用this()无参构造函数

public AnnotationConfigApplicationContext() {
/**
* 创建了一个Bean定义的读取器.
* 完成了spring内部BeanDefinition的注册(主要是后置处理器)
* 读取了很多spring自定义的配置(主要是后置处理器). 这些类都是spring 的原始类(也就是创世纪的类).
*/
this.reader = new AnnotatedBeanDefinitionReader(this); /**
* 创建BeanDefinition扫描器
* 可以用来扫描包或者类, 进而转换为bd
*
* Spring默认的扫描包不是这个scanner对象
* 而是自己new的一个ClassPathBeanDefinitionScanner
* Spring在执行工程后置处理器ConfigurationClassPostProcessor时, 去扫描包时会new一个ClassPathBeanDefinitionScanner
*
* 这里的scanner仅仅是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法
* 通过调用context.scan("package name");扫描处理配置类
* 扫描
*/
this.scanner = new ClassPathBeanDefinitionScanner(this);
}

在初始化AnnotatedBeanDefinitionReader(this);的时候, 注册了很多后置处理器

/**
* Register all relevant annotation post processors in the given registry.
* @param registry the registry to operate on
* @param source the configuration source element (already extracted)
* that this registration was triggered from. May be {@code null}.
* @return a Set of BeanDefinitionHolders, containing all bean definitions
* that have actually been registered by this call
*/
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) { // 获取到beanFactory
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
/**
* 判断beanFactory中是否有AnnotationAwareOrderComparator和ContextAnnotationAutowireCandidateResolver
* 没有则添加
*/
if (beanFactory != null) {
if (!
(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);

}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
} // BeanDefinitionHolder: 为BeanDefinition设置名字和别名
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8); // 如果registry中没有ConfigurationClassPostProcessor配置类后置处理器, 就添加一个
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
// 构建BeanDefinitionHolder, 并添加到beanDefs
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 如果rigistry中, 没有AutowiredAnnotationBeanPostProcessor Autowired注解bean的后置处理器, 则添加一个
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class
);
def.setSource(source);
// 构建BeanDefinitionHolder, 并添加到beanDefs
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
} // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
// 检查对JSR-250的支持, 如果rigistry中没有 CommonAnnotationBeanPostProcessor 通用注解后置处理器, 则添加一个
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class
);
def.setSource(source);
// 构建BeanDefinitionHolder, 并添加到beanDefs
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
} // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
// 检查对jpa的支持, 如果不包含 internalPersistenceAnnotationProcessor, 持久化注解处理器, 就添加一个
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class
.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
} // 检查对事件监听的支持, 如果不包含事件监听处理器 internalEventListenerProcessor, 就添加一个
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class
);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
} // 如果不包含事件监听工厂处理器 internalEventListenerFactory , 就添加一个
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class
);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
} return beanDefs;
}

我们看到, 注册了6个原始RootBeanDefinition, 这些bean是spring自己提前定义好的, 他们的加载是整个spring的基础. 用于解析spring中其他的类

而这一次我们要研究配置类是如何被读取的, 所以重点关注的是下面这个后置处理器

ConfigurationClassPostProcessor.class

这里还有很多其他的原始类被注册了, 但我们的目标是分析配置类是如何被读取的, 所以, 其他的先忽略, 只看ConfigurationClassPostProcessor.

3.2 ConfigurationClassPostProcessor的继承结构

可以看到ConfigurationClassPostProcessor是同时实现了BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor. 这一点我们需要记住, 后面会使用到

2.3 ConfigurationClassPostProcessor是如何被注册的

// 如果registry中没有ConfigurationClassPostProcessor配置类后置处理器, 就添加一个
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
// 构建BeanDefinitionHolder, 并添加到beanDefs
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}

首先,构建了一个RootBeanDefinition. 然后调用了registerPostProcessor方法, 三个入参分别是

registry: BeanDefinitionRegistry注册器, 用于注册BeanDefinition
def: 刚刚构建的RootBeanDefinition
CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME: 构建BeanDefinition使用的beanName是org.springframework.context.annotation.internalConfigurationAnnotationProcessor

然后调用registerPostProcessor方法

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException { Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
} // 从BeanDefinition的一级缓存BeanDefinitionMap中读取BeanDefinition对象, 判断是否已经存在
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);      // 这里,如果已经存在,说明被重复加载了, 那么后面加载的会覆盖前面加载的bean
if (existingDefinition != null) {
// 判断是否允许BeanDefinition重写
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
// 覆盖一级缓存的bean定义
this
.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// 处理循环引用的问题
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
} if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}

这里面的关键代码是标红的部分, 将ConfigurationClassPostProcessor放入到了beanDefinitionMap里面

下面的else是处理循环引用的问题, 暂时先不要看.

3.3 对照整体框架, 我们知道ConfigurationClassPostProcessor被解析成beanDefinition放入到BeanDefinitionMap中了

3.4 初始化ClassPathBeanDefinitionScanner

在this()构造方法里, 还初始化了ClassPathBeanDefinitionScanner, 这里只说一句.

this.scanner = new ClassPathBeanDefinitionScanner(this);

我们在扫描配置类的时候, 确实使用的是ClassPathBeanDefinitionScanner, 但是, 不是this.scanner对象. 而是自己new的一个ClassPathBeanDefinitionScanner.

这里的scanner仅仅是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法

通过调用context.scan("package name");扫描处理配置类

使用方式如下:

public static void main(String[] args) {
// 第一步: 通过AnnotationConfigApplicationContext读取一个配置类
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
context.scan("package");
Car car = (Car) context.getBean("car");
System.out.println(car.getName());
context.close();
}

到目前为止完成了后置处理器注册为BeanDefinition

备注: 

ConfigurationClassPostProcessor是一个工具类, 这个类的作用是解析配置类.

工具类有了, 那么还得有主角呀, 那就是我们上面的配置类. 下面看看配置类的加载

四. 读取自定义配置类MainConfig

注册配置类,入口自然是这里了

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
// 进入构造函数, 首先调用自身的构造方法this();
// 调用自身的构造方法之前, 要先调用父类的构造方法
this();
// register配置注册类
register(componentClasses);
// ioc容器shua新接口--非常重要
refresh();
}

跟踪进去找到doRegisterBean(...)方法

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) { // 将入参的配置类beanClass构建成AnnotatedGenericBeanDefinition对象
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
} abd.setInstanceSupplier(supplier);
// 读取配置类的元数据
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); // 处理主类通用定义注解
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}
// 将MainConfig.java配置类进行解析.放到BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

重点就是红色这句话, 其他可以略过, 因为我们的配置类很简单, 直接看BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

我们找到 registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());方法, 进入到DefaultListableBeanFactory查看方法, 这个方法之前我们已经调用过一次

就是在注册ConfigurationClassPostProcessor的时候, 我们需要将其解析为BeanDefinition然后放到BeanDefinitionMap中, 这里也是一样的, 将我们的配置类MainConfig解析成BeanDefinition放入到BeanDefinitionMap中.

这里的代码在整个框架中处于什么位置呢? 将MainConfig解析为BeanDefinition放入到BeanDefinitionMap中

以上两步, 一个是将ConfigurationClassPostProcessor配置类后置处理器, 也就是解析配置的工具类, 解析成BeanDefinition放入到BeanDefinitionMap中

另一个是将我们的目标配置类MainConfig加载到内存, 组装成BeanDefinition放入到BeanDefinitionMap中.

到这里,我们完成了两步.

第一步: 准备工具类ConfigurationClassPostProcessor

第二步: 准备配置类MainConfig.

接下俩, 就是要使用工具类来解析配置类MainConfig了

五. 调用bean工厂的后置处理器invokeBeanFactoryPostProcessors(beanFactory);

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
// 进入构造函数, 首先调用自身的构造方法this();
// 调用自身的构造方法之前, 要先调用父类的构造方法
this();
// register配置注册类
register(componentClasses);
// ioc容器刷新接口--非常重要
refresh();

在refresh()中有很多步骤, 我们重点来看invokeBeanFactoryPostProcessors(beanFactory);

/**
* refresh是spring最核心的方法, 里面包含了整个spring ioc的全过程, 包括spring加载bean到销毁bean的全过程
* 学习spring, 就是学习里面的13个方法, 如果13个方法都学完了, 基本上就打通了
* @throws BeansException
* @throws IllegalStateException
*/
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 准备刷新上下文环境
prepareRefresh(); // Tell the subclass to refresh the internal bean factory.
//2. 获取告诉子类初始化bean工厂, 不同工厂不同实现
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context.
//3. 对bean工厂进行填充属性
prepareBeanFactory(beanFactory); try {
// Allows post-processing of the bean factory in context subclasses.
// 4. 留个子类去实现该接口
postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context.
/*
*
* 调用bean工厂的后置处理器
* 我们之前在Reader的时候读取了很多创世纪的PostProcessor后置处理器.
* 这里要调用bean工厂的后置处理器. 这么多创世纪的PostProcessor, 只有一个PostProcessor实现了
* BeanFactoryPostProcessor. 那个类就是 ConfigurationClassPostProcessor
* 前面已经将ConfigurationClassPostProcessor放入到BeanDefinitionMap中了,
* 对应的BeanDefinitionName 是 internalConfigurationAnnotationProcessor
*
*
*
*/
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册bean后置处理器
registerBeanPostProcessors(beanFactory); // Initialize message source for this context.
// 初始化国际化资源处理器
initMessageSource(); // Initialize event multicaster for this context.
// 创建事件多播放器
initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.
// 这个方法通用也是留个子类实现的, spring boot也是从这个方法进行启动
onRefresh(); // Check for listener beans and register them.
// 将事件监听器注册到多播放器上
registerListeners(); // Instantiate all remaining (non-lazy-init) singletons.
// 实例化剩余的单实例bean
/**
* 这个方法就是循环遍历BeanDefinitionMap, 调用getBean, 去生产bean
*/
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
//最后容器刷新 发布刷新时间(spring cloud是从这里启动的 )
finishRefresh();
} ........
}

invokeBeanFactoryPostProcessors(beanFactory);看名字, 调用的是Bean工厂的后置处理器, 上面分析了, 初始化的时候初始化了很多spring原生的后置处理器, 这么多后置处理器, 其实, 只有一个后置处理器实现了BeanFactoryPostProcessor, 它就是ConfigurationClassPostProcessor, 还记得上面的结构图么, 拿下来, 再看一遍.

这里调用的时候, 原生处理器只会调用ConfigurationClassPostProcessor

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
/**
* 获取两处存储BeanFactoryPostProcessor的对象, 传入供接下来调用
* 1. 当前bean工厂
* 2. 和我们自己调用addBeanFacoryPostProcessor自定义BeanFactoryPostProcessor
*
* 参数: getBeanFactoryPostProcessors() 传了一个工厂的后置处理器的List, 这个时候list是空的
* getBeanFactoryPostProcessors()里面的值是怎么来的呢?
* 通过在自定义main方法中调用context.addBeanFactoryPostProcessor(...);来添加
*
* public static void main(String[] args) {
* // 第一步: 通过AnnotationConfigApplicationContext读取一个配置类
* AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
* context.addBeanFactoryPostProcessor(...);
* Car car = (Car) context.getBean("car");
* System.out.println(car.getName());
* context.close();
* }
*/

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
    ......
}

这里要调用bean工厂的后置处理器了. 看上面的注释, 注释写的很清晰.

在调用PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());的时候调用了getBeanFactoryPostProcessors()方法. 

  public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
return this.beanFactoryPostProcessors;
}
getBeanFactoryPostProcessors() 返回的是一个工厂的后置处理器的List, 这个时候list是空的
getBeanFactoryPostProcessors()里面的值是怎么来的呢?
通过在自定义main方法中调用context.addBeanFactoryPostProcessor(...);来添加. 也就是通过main方法手动添加的beanFactoryPostProcessor. 如下所示
public static void main(String[] args) {
// 第一步: 通过AnnotationConfigApplicationContext读取一个配置类
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
context.addBeanFactoryPostProcessor(...);
Car car = (Car) context.getBean("car");
System.out.println(car.getName());
context.close();
}

接下来重点来了. PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); 方法实现一共分为两大步:

第一步: 调用所有实现了 BeanDefinitionRegistryPostProcessor 接口的bean定义. (BeanDefinitionRegistryPostProcessor带注册功能的后置处理器)

第二步: 调用BeanFactoryPostProcessor Bean工厂的后置处理器

第一步: 调用所有实现了 BeanDefinitionRegistryPostProcessor 接口的bean定义.

来看看源码是如何定义的. 重点看代码的注释, 每一部分的功能都有明确标出, 注释写的很详细

public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { /**
* 首先,调用BeanDefinitionRegistryPostProcessors的后置处理器
* 定义已处理的后置处理器
*/
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>(); /**
* 这里一共分为两大步:
* 第一步: 调用所有实现了 BeanDefinitionRegistryPostProcessor 接口的bean定义. (BeanDefinitionRegistryPostProcessor带注册功能的后置处理器)
* 第二步: 调用BeanFactoryPostProcessor Bean工厂的后置处理器
*/ /**********************第一步: 调用所有实现了BeanDefinitionRegistryPostProcessor接口的bean定义 begin****************************/
// 判断beanFactory是否实现了BeanDefinitionRegistry, 实现了该结构就有注册和获取Bean定义的能力
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
} // 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.
/**
* 这是一个集合, 存马上即将要被调用的BeanDefinitionRegistryPostProcessor
*/
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 第一步, 调用实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors
// 在所有创世纪的后置处理器中, 只有 internalConfigurationAnnotationProcessor 实现了 BeanDefinitionRegistryPostProcessors 和 PriorityOrdered
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 判断beanFactory是否实现了PriorityOrdered接口. 如果实现了,是最优先调用.
// 在整个加载过程中,会调用四次BeanDefinitionRegistryPostProcessor, 而实现了PriorityOrdered的接口最先调用
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 调用beanFactory.getBean实例化创世界的类ppName
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
/**
* 第一次调用BeanDefinitionRegistryPostProcessors
* 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor
* 用于进行bean定义的加载 比如我们的包扫描 @import 等
*/
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 处理完了,清空currentRegistryProcessors
currentRegistryProcessors.clear(); // 第二步: 调用实现 Ordered 的 BeanDefinitionRegistryPostProcessors。
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 这时实现了PriorityOrdered.class的postProcessor就不会再被加载进来了, 因为processedBeans.contains(ppName) == true
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
// 将其放入到currentRegistryProcessors, 马上就要被调用
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
} // 对所有的处理器进行排序. 调用了Ordered的方法, 会返回排序(一个数字), 然后根据数字排序即可
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors); /**
* 第二次调用BeanDefinitionRegistryPostProcessors
* 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor
* 用于进行bean定义的加载 比如我们的包扫描 @import 等
*/
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

currentRegistryProcessors.clear(); // 第三步. 调用没有实现任何优先级接口的 BeanDefinitionRegistryPostProcessor
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
// 获取
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 已处理过的postProcessor不再处理
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
/**
* 第三次调用BeanDefinitionRegistryPostProcessors
* 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor
* 用于进行bean定义的加载 比如我们的包扫描 @import 等
*/
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

currentRegistryProcessors.clear();
} // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
/*
* 第四步:调用bean工厂的后置处理器
* registryProcessors: 带有注册功能的bean工厂的后置处理器
* regularPostProcessors: 不带注册功能的bean工厂的后置处理器
*/
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

} else {
/*
* 如果当前的beanFactory没有实现BeanDefinitionRegistry 说明没有注册Bean定义的能力
* 那么就直接调用 BeanDefinitionRegistryPostProcessor.postProcessBeanFactory方法
*/ // Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
} /**********************第一步: 调用所有实现了BeanDefinitionRegistryPostProcessor接口的bean定义 end****************************/ /**********************第二步: 调用BeanFactoryPostProcessor Bean工厂的后置处理器 begin****************************/ // 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.
// 优先排序的后置处理器
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
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);
}
} // 首先, 调用有优先级排序的后置处理器
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // 第二, 调用实现了Ordered排序的后置处理器
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // 最后, 调用没有实现任何排序接口的beanFactory后置处理器
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); /**********************第二步: 调用BeanFactoryPostProcessor Bean工厂的后置处理器 end****************************/
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}

下面我们就来分析上图所示的内容.

1. 对照源码和上图, 我们来看第一次调用

        // 第一次, 调用实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors
// 在所有创世纪的后置处理器中, 只有 internalConfigurationAnnotationProcessor 实现了 BeanDefinitionRegistryPostProcessors 和 PriorityOrdered
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 判断beanFactory是否实现了PriorityOrdered接口. 如果实现了,是最优先调用.
// 在整个加载过程中,会调用四次BeanDefinitionRegistryPostProcessor, 而实现了PriorityOrdered的接口最先调用
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 调用beanFactory.getBean实例化创世界的类ppName
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
/**
* 第一次调用BeanDefinitionRegistryPostProcessors
* 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor
* 用于进行bean定义的加载 比如我们的包扫描 @import 等
*/
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 处理完了,清空currentRegistryProcessors
currentRegistryProcessors.clear();

首先, 拿到了所有实现了BeanDefinitionRegistryPostProcessor的后置处理器, 上面我们做过铺垫,只有ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor后置处理器

所以,这里过滤出来的postProcessorNames只有一个,就是ConfigurationClassPostProcessor, 接下来, 判断这个类是否实现了PriorityOrdered 优先排序的接口, 如果实现了, 那么放入到currentRegistryProcessors中, 后面会进行调用.

接下来, 执行invokeBeanDefinitionRegistryPostProcessors

这是第一次调用BeanDefinitionRegistryPostProcessors

2. 第二次调用BeanDefinitionRegistryPostProcessors

        // 第二步: 调用实现 Ordered 的 BeanDefinitionRegistryPostProcessors。
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 这时实现了PriorityOrdered.class的postProcessor就不会再被加载进来了, 因为processedBeans.contains(ppName) == true
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
// 将其放入到currentRegistryProcessors, 马上就要被调用
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
} // 对所有的处理器进行排序. 调用了Ordered的方法, 会返回排序(一个数字), 然后根据数字排序即可
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors); /**
* 第二次调用BeanDefinitionRegistryPostProcessors
* 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor
* 用于进行bean定义的加载 比如我们的包扫描 @import 等
*/
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

currentRegistryProcessors.clear();

第二次调用的时候 ,依然是获取所有的实现了BeanDefinitionRegistryPostProcessor接口的后置处理器, 且这个处理器没有实现过PriorityOrdered也就是没有被上面调用过. 且实现了Ordered接口

这一类添加到currentRegistryProcessors集合中, 然后调用invokeBeanDefinitionRegistryPostProcessors处理

这是第二次调用BeanDefinitionRegistryPostProcessor

3. 第三次调用BeanDefinitionRegistryPostProcessor

         // 第三步. 调用没有实现任何优先级接口的 BeanDefinitionRegistryPostProcessor
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
// 获取
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 已处理过的postProcessor不再处理
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
/**
* 第三次调用BeanDefinitionRegistryPostProcessors
* 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor
* 用于进行bean定义的加载 比如我们的包扫描 @import 等
*/
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

currentRegistryProcessors.clear();
}

第三次调用的是没有实现过任何排序接口的后置处理器. 并将其放入到currentRegistryProcessors, 然后执行invokeBeanDefinitionRegistryPostProcessors

4. 第四次调用

// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
/*
* 调用bean工厂的后置处理器
* registryProcessors: 带有注册功能的bean工厂的后置处理器
* regularPostProcessors: 不带注册功能的bean工厂的后置处理器
*/
// 调用BeanDefinitionRegistryPostProcessor.postProcessBeanFactory方法----为什么是调用BeanDefinitionRegistryPostProcessor? 因为
// ConfigurationClassPostProcessor 实现了 BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessors
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 调用BeanFactoryPostProcessor 自设的(ConfigurationClassPostProcessor没有)
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

ConfigurationClassPostProcessor同时实现了BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessors, 调用的是invokeBeanFactoryPostProcessors

一共进行了4次调用

总结: 优先处理的是实现了PriorityOrdered的后置处理器, 然后调用实现了Order接口的后置处理器, 最后调用了没有实现任何排序方法的后置处理器. 最后调用工厂类方法.

下面我们来具体分析invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);

5. 提问: 检验一下是否理解了上面四个步骤

1. ConfigurationClassPostProcessor会调用1234哪几步?

因为ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor,PriorityOrdered, 因此会调用1,4

2. 如果自己定义了一个MyBeanFactoryPostProcessor会调用1234那几步?

package com.lxl.www.iocbeanlifecicle;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.stereotype.Component; @Component
public class MyBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { } @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { }
} 因为MyBeanFactoryPostProcessor是自定义的, 没有实现任何PriorityOrdered 或者 Order, 因此, 会调用3,4

二. 详细研究第四步, invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);的逻辑.

我们在这一步打个断点, 然后跟着断点一步一步点击进去

这是registryProcessors里面只有一个后置处理器, 就是ConfigurationClassPostProcessor.

然后进入到ConfigurationClassPostProcessor.postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法

@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);
} // 使用 cglib 配置类进行代理, 因为@Bean方法到时候要进行创建Bean的实例.
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

这里先看enhanceConfigurationClasses(beanFactory);个方法

public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>(); for (String beanName : beanFactory.getBeanDefinitionNames()) {
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) {
// Configuration class (full or lite) or a configuration-derived @Bean method
// -> resolve bean class at this point...
AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
if (!abd.hasBeanClass()) {
try {
abd.resolveBeanClass(this.beanClassLoader);
}
catch (Throwable ex) {
throw new IllegalStateException(
"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
} /**
* 只有full版配置才会创建cglib代理
* full是怎么来的呢? 我们使用@Configuration注解了, 在加载的时候, 就会设置为full
* 当设置为full以后, 我们在调用的时候, 就会创建一个cglib动态代理.
*
* 为什么要创建动态代理呢?
* 动态代理可以保证, 每次创建的bean对象只有一个
*
* 那么加@Configuration和不加本质上的区别是什么?
* 当在配置类中一个@Bean使用方法的方式引入另一个Bean的时候, 如果不加@Configuration注解, 就会重复加载Bean
* 如果加了@Configuration, 则会在这里创建一个cglib代理, 当调用了@Bean方法是会先检测容器中是否存在这个Bean, 如果不存在则创建, 存在则直接使用.
*/
if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
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'."
);
}
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}

}
if (configBeanDefs.isEmpty()) {
// nothing to enhance -> return immediately
return;
} 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);
// Set enhanced subclass of the user-specified bean class
Class<?> configClass = beanDef.getBeanClass();
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);
}
}
}

粗体部分就是判断是否需要进行cglib代理. 进行cglib代理的条件是, beanDefinition中属性configurationClass的值是full. 只有full版配置才会创建cglib代理

那么有下面几个问题:

问题1: full版本配置是什么呢?

我们使用@Configuration注解了, 在加载的时候, 就会将configurationClass属性设置为full.当设置为full以后, 我们在调用的时候, 就会创建一个cglib动态代理.

问题2: 为什么要创建动态代理呢?

动态代理可以保证, 每次创建的bean对象只有一个

问题3:那么加@Configuration和不加本质上的区别是什么?

当在配置类中一个@Bean使用方法的方式引入另一个Bean的时候, 如果不加@Configuration注解, 就会重复加载Bean.如果加了@Configuration, 则会在这里创建一个cglib代理, 当调用了@Bean方法是会先检测容器中是否存在这个Bean, 如果不存在则创建, 存在则直接使用.

问题4:full是怎么来的呢?

这是在上面调用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);接口的时候, 标记的是full还是Lite

下面来看一下源码

在这里一步,执行的时候,进行了这个类是full的还是lite,继续忘下看

此时满足条件的postProcessor只有一个, 那就是ConfigurationClassPostProcessor. 下面直接看ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()方法

前面都是一些条件判断, 重点看processConfigBeanDefinitions(registry);

在这里,这个方法判断了, 这个类是full的还是lite的. 下面直接上代码

/**
* Check whether the given bean definition is a candidate for a configuration class
* (or a nested component class declared within a configuration/component class,
* to be auto-registered as well), and mark it accordingly.
* @param beanDef the bean definition to check
* @param metadataReaderFactory the current factory in use by the caller
* @return whether the candidate qualifies as (any kind of) configuration class
*/
public static boolean checkConfigurationClassCandidate(
BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) { String className = beanDef.getBeanClassName();
if (className == null || beanDef.getFactoryMethodName() != null) {
return false;
} AnnotationMetadata metadata;
// 获取元数据
if (beanDef instanceof AnnotatedBeanDefinition &&
className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
// Can reuse the pre-parsed metadata from the given BeanDefinition...
metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
}
else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
// Check already loaded Class if present...
// since we possibly can't even load the class file for this Class.
Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
BeanPostProcessor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
EventListenerFactory.class.isAssignableFrom(beanClass)) {
return false;
}
metadata = AnnotationMetadata.introspect(beanClass);
}
else {
try {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
metadata = metadataReader.getAnnotationMetadata();
}
catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not find class file for introspecting configuration annotations: " +
className, ex);
}
return false;
}
} // 判断元数据中是否包含Configuration注解
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
/**
* 判断, proxyBeanMethods属性是否为true, 如果为true就是一个完全的类,
* 也就是带有@Configuration注解, 设置Configuration_class属性为full
*
* proxyBeanMethods配置类是用来指定@Bean注解标注的方法是否使用代理,
* 默认是true使用代理,直接从IOC容器之中取得对象;
* 如果设置为false,也就是不使用注解,每次调用@Bean标注的方法获取到的对象和IOC容器中的都不一样,是一个新的对象,所以我们可以将此属性设置为false来提高性能。
*/

if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
// 判断是不是带了@Component, @ComponentScan @Import @ImportResource @Bean注解,
// 如果带有这几种注解, 就将其Configuration_class属性为lite类型的配置类

else if (config != null || isConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
} // It's a full or lite configuration candidate... Let's determine the order value, if any.
Integer order = getOrder(metadata);
if (order != null) {
beanDef.setAttribute(ORDER_ATTRIBUTE, order);
} return true;
}

上面主要是获取元数据, 然后判断元数据中是否有Configuration注解. 如果有,返回其属性. 我们判断其属性中proxyBeanMethods是否true, 如果是true, 那么将其设置为full.

如果配置中带有@Component, @ComponentScan @Import @ImportResource @Bean这几种属性之一, 那么就将其设置为lite.

问题5: cglib动态代理做了什么事情呢?

不看源码的情况下, 简单可以理解为, 去ioc工厂里面通过getBean("car") 查询了看ioc中是否有这个对象, 如果有就取出来, 不再另创建.

这也是@Configuration 和其他注解类似@Component和@ComponentScan的本质区别:

当在配置类中一个@Bean使用方法的方式引入另一个Bean的时候, 如果不加@Configuration注解, 就会重复创建Bean

如果加了@Configuration, 则会在这里创建一个cglib代理, 当调用了@Bean方法是会先检测容器中是否存在这个Bean, 如果不存在则创建, 存在则直接使用.

下面来看个例子

基础类:
public class Car {
private String name;
private Tank tank; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Tank getTank() {
return tank;
} public void setTank(Tank tank) {
this.tank = tank;
}
} public class Tank {
private String name; public Tank() {
System.out.println("创建一个tank");
}
public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} }

这是定义的car和tank的基础类

@Configuration
@ComponentScan(basePackages = {"com.lxl.www.iocbeanlifecicle"})
public class MainConfig { @Bean("car")
public Car car() {
Car car = new Car();
car.setName("zhangsan");
// 这里调用了Tank类, tank是通过@Bean注解注入的.
car.setTank(tank());
return car;
} @Bean
public Tank tank() {
return new Tank();
}
}

当配置类使用了@Configuration注解的时候, 运行main方法

public class MainStarter {
public static void main(String[] args) {
// 第一步: 通过AnnotationConfigApplicationContext读取一个配置类
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
context.scan("package");
//context.addBeanFactoryPostProcessor();
Car car = (Car) context.getBean("car");
Car car2 = (Car) context.getBean("car");
System.out.println(car.getName());
context.close();
}
}

当去掉@Configuration注解的时候, 再次运行, 我们看到创建了两次tank

//@Configuration
@ComponentScan(basePackages = {"com.lxl.www.iocbeanlifecicle"})
public class MainConfig { @Bean("car")
public Car car() {
Car car = new Car();
car.setName("zhangsan");
// 这里调用了Tank类, tank是通过@Bean注解注入的.
car.setTank(tank());
return car;
} @Bean
public Tank tank() {
return new
Tank();
}

}

在main方法中调用了两次(Car) context.getBean("car");

在new一个对象的时候, 如果不取ioc容器中取, 那么每一次都会创建一个新的.

在ioc容器中, car对象只有一个, 但是在构建car的时候, 调用了tank, tank在ioc容器中却不一定只有一份. 只有使用了@Configuration, 表示需要使用cglib动态代理查找tank类, 保证ioc容器中只有一份.

7. 详细研究四次调用中的第一次调用.  通过分析跟踪@ComponentScan注解是如何解析的,

通过跟踪@ComponentScan注解是如何解析的, 分来理解BeanDefinitionScan, BeanDefinitionRegistry, BeanDefinitionReader是如何工作的.

public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { /**
* 首先,调用BeanDefinitionRegistryPostProcessors 的后置处理器
* 定义已处理的后置处理器
*/
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>(); /**
* 这里一共分为两大步:
* 第一步: 调用所有实现了 BeanDefinitionRegistryPostProcessor 接口的bean定义. (BeanDefinitionRegistryPostProcessor带注册功能的后置处理器)
* 第二步: 调用BeanFactoryPostProcessor Bean工厂的后置处理器
*/ /**********************第一步: 调用所有实现了BeanDefinitionRegistryPostProcessor接口的bean定义 begin****************************/
// 判断beanFactory是否实现了BeanDefinitionRegistry, 实现了该结构就有注册和获取Bean定义的能力
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
} // 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.
/**
* 这是一个集合, 存马上即将要被调用的BeanDefinitionRegistryPostProcessor
*/
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 首先, 调用实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors
// 在所有创世纪的后置处理器中, 只有 internalConfigurationAnnotationProcessor 实现了 BeanDefinitionRegistryPostProcessors 和 PriorityOrdered
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 判断beanFactory是否实现了PriorityOrdered接口. 如果实现了,是最优先调用.
// 在整个加载过程中,会调用四次BeanDefinitionRegistryPostProcessor, 而实现了PriorityOrdered的接口最先调用
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 调用beanFactory.getBean实例化配置类的后置处理器(创世界的类ppName), 也就是初始化, 实例化, 赋值属性.
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
/**
* 第一次调用BeanDefinitionRegistryPostProcessors
* 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor
* 用于进行bean定义的加载 比如我们的包扫描 @import 等
*/
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 处理完了,清空currentRegistryProcessors
currentRegistryProcessors.clear();

这里也有两大步

第一步: 初始化bean工厂的后置处理器

  通过调用beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class) 初始化了bean工厂的后置处理器,

第二步: 解析配置

   调用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);调用beanDefinitionRegistry的后置处理器. 筛选出符合条件的配置类. 

如上图所示, 最后筛选出的配置类只有MainConfig配置类. 也就是说configCandidates配置候选集合中只有一个MainConfig

      // 创建一个ConfigurationClassParser对象, 解析@Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this
.componentScanBeanNameGenerator, registry); Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
// 执行解析
parser.parse(candidates);
parser.validate();

然后, 接下来创建了一个对象ConfigurationClassParser, 这是一个配置类解析器. 下面将使用这个解析器解析配置类.

重点是如何解析的, 代码已重点标注出来了.

 // 执行解析
parser.parse(candidates);

我们这里是通过注解解析的, 所以直接看下面的代码

public void parse(Set<BeanDefinitionHolder> configCandidates) {
// 循环配置类
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
// 真正的解析bean定义:通过注解元数据解析
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
......
}

解析主要做了几件事呢?如下图:

解析配置类, 看看配置类是否含有如上标记的注解, 如果有, 则调用响应的返回对其进行解析,处理.

下面来看看源码. 是如何处理这一块的.

/**
* 在这里会解析@Component @PropertySources @ComponentScan @ImportResource
* @param configClass
* @param sourceClass
* @param filter
* @return
* @throws IOException
*/
@Nullable
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException { // 1. 处理@Component注解,判断元数据是否带有Component注解
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass, filter);
} // Process any @PropertySource annotations
// 2. 处理@PropertySource 注解, 判断元数据是否带有@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");
}
} // Process any @ComponentScan annotations
// 3. 处理@ComponentScan注解, 判断元数据是否带有@ComponentScan注解
/**
* 这里mainConfig配置类中有两个注解,一个是@Configuration ,一个是@ComponentScan. 在这里, 我们看一下@ComponentScan
*/
//componentScans 拿到的就是ComponentScan注解里的属性
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
// 解析扫描出来的类, 将其解析为BeanDefinitionHolder对象, 并放入到scannedBeanDefinitions中
// 这正的解析ComponentScans和ComponentScan中的配置
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// 循环处理包扫描出来的bean定义
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
// 判断当前扫描出来的是不是一个配置类, 如果是的话, 直接进行递归解析.
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
} // 4. 处理@Import注解
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), filter, true); // 5. 处理@ImportResource注解
// Process any @ImportResource annotations
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);
}
} // 6. 处理@Bean注解
// Process individual @Bean methods
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
} // 处理默认方法
// Process default methods on interfaces
processInterfaces(configClass, sourceClass); // 处理超类
// Process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
} // No superclass -> processing is complete
return null;
}

下面我们重点看对@ComponentScan和@ComponentScans注解的解析, 为什么看他呢? 因为很多注解都标记了@Component注解.

比如@Service注解,本身使用@Component

再来看@Controller注解, 其实质也是一个@Component注解

我们在自定义配置类的时候, 会使用@ComponentScan注解. 并传递一个包, 作为扫描包. 如MainConfig配置

这就会扫描包下所有的配置类.

它主要的逻辑如下:

在拿到@ComponentScan注解以后, 会对其进行parse. 主要解析里面的注解. 并对每一个注解进行处理. 处理后将其添加到scanner属性中. 最后调用scanner.doScan(....)方法.

源码如下:

// 解析配置
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
// 定义了一个类路径扫描器ClassPathBeanDefinitionScanner
// 这里的scanner用于读取配置类
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
// 1. 判断是否有nameGenerator注解
// 为扫描器设置beanName的生成器对象, 并赋值给scanner, BeanNameGenerator的作用是为bean definitions生成Bean名字的接口
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
BeanUtils.instantiateClass(generatorClass)); // 2. 判断是否有scopedProxy注解
ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
scanner.setScopedProxyMode(scopedProxyMode);
}
else {
Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
} scanner.setResourcePattern(componentScan.getString("resourcePattern")); // 3. 判断属性中是否有includeFilters属性, 有的话就添加到scanner中
// 设置componentScan中包含的过滤器 -- 在使用注解的时候配置了包含和排除的过滤器, 这里进行处理
for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addIncludeFilter(typeFilter);
}
} // 4. 判断属性总是否有excludeFilters属性, 有的话放到scnanner中
// 设置componentScan中排除的过滤器
for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addExcludeFilter(typeFilter);
}
} // 5. 判断是否有lazyInit属性
// 获取配置类中懒加载初始化的属性
boolean lazyInit = componentScan.getBoolean("lazyInit");
if (lazyInit) {
scanner.getBeanDefinitionDefaults().setLazyInit(true);
} Set<String> basePackages = new LinkedHashSet<>(); // 6. 判断是否有basePackages属性
// 获取basePackages属性, 也就是我们定义的包扫描路径
String[] basePackagesArray = componentScan.getStringArray("basePackages");
for (String pkg : basePackagesArray) {
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
Collections.addAll(basePackages, tokenized);
}
for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
} scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
@Override
protected boolean matchClassName(String className) {
return declaringClass.equals(className);
}
}); // 调用scanner.doScan()方法, 扫描basePackages包
return scanner.doScan(StringUtils.toStringArray(basePackages));
}

调用doScan方法扫描配置类. 我们来看看主要做了哪些事情

第一步: 找到所有候选的BeanDefinition.

  上面解析出了@ComponentScan注解传递过来的basePackages包. 扫描包中所有的类, 得到候选类.

  扫描的时候做了几件事呢? 看最上图最右侧部分. 这扫描出来就是我们的目标类.

第二步: 解析这些准目标类.

第三步: 设置默认的beanDefinition属性

/**
* 设置默认的bean定义的信息
* Apply the provided default values to this bean.
* @param defaults the default settings to apply
* @since 2.5
*/
public void applyDefaults(BeanDefinitionDefaults defaults) {
// 设置这个类是不是懒加载的
Boolean lazyInit = defaults.getLazyInit();
if (lazyInit != null) {
setLazyInit(lazyInit);
}
// 设置默认的自动装配方式
setAutowireMode(defaults.getAutowireMode());
setDependencyCheck(defaults.getDependencyCheck());
// 设置初始化方法的名称
setInitMethodName(defaults.getInitMethodName());
// 是否可以调用InitMethod方法
setEnforceInitMethod(false);
setDestroyMethodName(defaults.getDestroyMethodName());
// 是否可以调用DestroyMethod方法
setEnforceDestroyMethod(false);
}

第四步: 将解析出来的bean定义注册到ioc容器中

这里就调用了BeanDefinitionReaderUtils.registerBeanDefinition注册bean定义. 之前注册过配置类, 这里和其是一样的. 所以不再赘述了

到此为止, 就将MainConfig配置类解析完并注册到ioc容器中了.

2.3 spring5源码系列---内置的后置处理器PostProcess加载源码的更多相关文章

  1. Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析

    Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析 前言 上一篇文章Spring Ioc源码分析系列--Ioc源码入口分析已经介绍到Ioc容器 ...

  2. Java安全之动态加载字节码

    Java字节码 简单说,Java字节码就是.class后缀的文件,里面存放Java虚拟机执行的指令. 由于Java是一门跨平台的编译型语言,所以可以适用于不同平台,不同CPU的计算机,开发者只需要将自 ...

  3. Android动态加载字节码

    概述 面对App业务逻辑的频繁变更,如果每一次改变都对App进行一次升级,会降低App的用户体验,那么App进行模块化升级(这里与增量升级是不同的)是很好的解决方案,让用户在完全无感觉的情况下改变Ap ...

  4. nuget.org 无法加载源 https://api.nuget.org/v3/index.json 的服务索引

    今天添加新项目想添加几个工具包,打开NuGet就这样了  发生错误如下: [nuget.org] 无法加载源 https://api.nuget.org/v3/index.json 的服务索引. 响应 ...

  5. nuget.org 无法加载源 https://api.nuget.org/v3/index.json 的服务索引 不定时抽风

    今天添加新项目想添加几个工具包,打开NuGet就这样了  发生错误如下: [nuget.org] 无法加载源 https://api.nuget.org/v3/index.json 的服务索引.响应状 ...

  6. 使用的jQuery加载源的优势【问题】

    [问题]使用的jQuery加载源的优势? [答案]许多用户在访问其他站点时,已经从谷歌或微软加载过 jQuery.所有结果是,当他们访问您的站点时,会从缓存中加载 jQuery,这样可以减少加载时间. ...

  7. 【easyui】treegrid逐级加载源码

    当初看这源码的目的是: 1.treegrid是怎么实现逐级加载树结构的. 解: 见demo,主要就是点击节点的时候会请求后台. 2.treegrid加载后,第二次展开节点会不会再次请求后台. 解:第二 ...

  8. 鸿蒙内核源码分析(进程镜像篇)|ELF是如何被加载运行的? | 百篇博客分析OpenHarmony源码 | v56.01

    百篇博客系列篇.本篇为: v56.xx 鸿蒙内核源码分析(进程映像篇) | ELF是如何被加载运行的? | 51.c.h.o 加载运行相关篇为: v51.xx 鸿蒙内核源码分析(ELF格式篇) | 应 ...

  9. springMVC容器加载源码分析

    springmvc是一个基于servlet容器的轻量灵活的mvc框架,在它整个请求过程中,为了能够灵活定制各种需求,所以提供了一系列的组件完成整个请求的映射,响应等等处理.这里我们来分析下spring ...

随机推荐

  1. Java 审计之XXE篇

    Java 审计之XXE篇 0x00 前言 在以前XXE漏洞了解得并不多,只是有一个初步的认识和靶机里面遇到过.下面来 深入了解一下该漏洞的产生和利用. 0x01 XXE漏洞 当程序在解析XML输入时, ...

  2. 063 01 Android 零基础入门 01 Java基础语法 08 Java方法 01 无参无返回值方法

    063 01 Android 零基础入门 01 Java基础语法 08 Java方法 01 无参无返回值方法 本文知识点:无参无返回值方法 无参无返回值方法 案例 为什么使用方法?--方便复杂问题调用 ...

  3. 剑指Offer(三):从尾到头打印链表

    一.前言 刷题平台:牛客网 二.题目 输入一个链表,返回一个反序的链表. 1.思路 通常,这种情况下,我们不希望修改原链表的结构.返回一个反序的链表,这就是经典的"后进先出",我们 ...

  4. 从远程库github.com克隆代码时遇到了如下的问题:

    Warning: Permanently added the RSA host key for IP address '13.250.177.223' to the list of known hos ...

  5. docker 搭建LNMP网站平台

    准备好镜像 1.创建网络 docker network create lnmp 测试环境需删除全部之前起的容器 docker rm -f $(docker ps -a |awk '{print $1} ...

  6. 【Redis之疑难解析】(error) READONLY You can't write against a read only slave

    一.问题描述 已部署好 Redis 主从服务器,实现了数据的同步. Redis 主服务器(master server)具有读写的权限,而 从服务器(slave master)默认 只具有 读 的权限. ...

  7. java中的t怎么用

    <T> T表示返回值是一个泛型,传递啥,就返回啥类型的数据,而单独的T就是表示限制你传递的参数类型,这个案例中,通过一个泛型的返回方式,获取每一个集合中的第一个数据, 通过返回值<T ...

  8. day24 Pyhton学习 反射

    一.isinstance,type,issubclass issubclass() 这个内置函数可以帮我们判断x类是否是y类的子类 issubclass(x,y) class Base: pass c ...

  9. day18 Pyhton学习 匿名函数

    匿名函数 别称: lambda表达式 函数,没有名字 def wahaha(n):#wahaha return n**2 print(wahaha.__name__) qqxing = lambda ...

  10. 这里有40条提升编程技能小妙招!还有TIOBE 7月份的编程语言排行榜

    如何提高编程技能?恐怕很多开发者思考过这个问题.最近,拥有将近 15 年开发经验的软件工程师 Kesk -*- 写了一篇博客,列举了 40 条对其职业生涯有所帮助的事项.   或许,通过以下 40 个 ...