2.3 spring5源码系列---内置的后置处理器PostProcess加载源码
本文涉及主题
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加载源码的更多相关文章
- Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析
Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析 前言 上一篇文章Spring Ioc源码分析系列--Ioc源码入口分析已经介绍到Ioc容器 ...
- Java安全之动态加载字节码
Java字节码 简单说,Java字节码就是.class后缀的文件,里面存放Java虚拟机执行的指令. 由于Java是一门跨平台的编译型语言,所以可以适用于不同平台,不同CPU的计算机,开发者只需要将自 ...
- Android动态加载字节码
概述 面对App业务逻辑的频繁变更,如果每一次改变都对App进行一次升级,会降低App的用户体验,那么App进行模块化升级(这里与增量升级是不同的)是很好的解决方案,让用户在完全无感觉的情况下改变Ap ...
- nuget.org 无法加载源 https://api.nuget.org/v3/index.json 的服务索引
今天添加新项目想添加几个工具包,打开NuGet就这样了 发生错误如下: [nuget.org] 无法加载源 https://api.nuget.org/v3/index.json 的服务索引. 响应 ...
- nuget.org 无法加载源 https://api.nuget.org/v3/index.json 的服务索引 不定时抽风
今天添加新项目想添加几个工具包,打开NuGet就这样了 发生错误如下: [nuget.org] 无法加载源 https://api.nuget.org/v3/index.json 的服务索引.响应状 ...
- 使用的jQuery加载源的优势【问题】
[问题]使用的jQuery加载源的优势? [答案]许多用户在访问其他站点时,已经从谷歌或微软加载过 jQuery.所有结果是,当他们访问您的站点时,会从缓存中加载 jQuery,这样可以减少加载时间. ...
- 【easyui】treegrid逐级加载源码
当初看这源码的目的是: 1.treegrid是怎么实现逐级加载树结构的. 解: 见demo,主要就是点击节点的时候会请求后台. 2.treegrid加载后,第二次展开节点会不会再次请求后台. 解:第二 ...
- 鸿蒙内核源码分析(进程镜像篇)|ELF是如何被加载运行的? | 百篇博客分析OpenHarmony源码 | v56.01
百篇博客系列篇.本篇为: v56.xx 鸿蒙内核源码分析(进程映像篇) | ELF是如何被加载运行的? | 51.c.h.o 加载运行相关篇为: v51.xx 鸿蒙内核源码分析(ELF格式篇) | 应 ...
- springMVC容器加载源码分析
springmvc是一个基于servlet容器的轻量灵活的mvc框架,在它整个请求过程中,为了能够灵活定制各种需求,所以提供了一系列的组件完成整个请求的映射,响应等等处理.这里我们来分析下spring ...
随机推荐
- VueX中state变化捕捉不到_getters监测不到state的变化
原因 可能有多种原因, 现在我说一下我碰到的一种情况: state种有一个变量叫state,它是一个json对象, 可把我害惨了.因为他这个json长这个样: messageBox:{ friendI ...
- Jboss未授权访问漏洞复现
一.前言 漏洞原因:在低版本中,默认可以访问Jboss web控制台(http://127.0.0.1:8080/jmx-console),无需用户名和密码. 二.环境配置 使用docker搭建环境 ...
- web框架推导
django 引言 所有的web应用本质上就是一个socket服务端,而用户的浏览器. 软件开发架构 cs架构 bs架构 本质上,bs架构也是cs架构 http协议 网络协议 http协议 数据传输是 ...
- Jetson AGX Xavier/Ubuntu安装QT
安装QT命令 sudo apt-get install qt5-default qtcreator -y 如果出现错误:unknow module webenginewidgets serialpor ...
- CentOS 7安装Nginx 1.10.2
安装epel-release源并进行安装 yum install epel-release yum update(时间会有点长) yum install nginx 相关操作: systemctl s ...
- LiteOS-任务篇-源码分析-任务调度函数
目录 前言 笔录草稿 核心源码分析 osTaskSchedule函数源码分析 osPendSV函数源码分析 TaskSwitch函数源码分析 调度上层源码分析 osSchedule函数源码分析 LOS ...
- Python+Appium自动化测试(8)-swipe()滑动页面
app自动化测试过程中,经常会遇到滑动屏幕操作,appium框架的话我们可以使用webdriver提供的swipe()方法来对屏幕页面进行上滑.下滑.左滑.右滑操作. 一,swipe方法介绍 swip ...
- Struts2 学习记录-第一天
Struts2 -01 struts2框架认识 struts2框架是web层框架.struts2框架=webwork+strut1框架发展过来的.struts2框架设计主要用到技术:通过过滤器进行请求 ...
- Mysql架构与内部模块-第一章
Mysql作为大多数中小型企业的首选数据库,也可能是众多同僚接触的第一个数据库,其热门程度不言而喻,一些相对基础的知识本系列不做赘述,主要简述Mysql相关的进阶知识. 本章将由浅入深的讲解从连接My ...
- day44 Pyhton 数据库Mysql
内容回顾 什么是进程? 就是为了形容执行中的程序的一种称呼 它是操作系统中资源分配的最小单位 进程之间是数据隔离的,占用操作系统资源相对多 独立存在的 谈谈你对并发的理解 同时有多个任务需要执行,但是 ...