- 一、Spring 核心概念
- 二、Spring 体系结构
- 二、Spring 应用
- 三、Spring 重要接口
- 四、IOC 容器
- 五、AOP
- 六、事物
- 七、Spring 启动流程
- STEP1、prepareFresh()
- STEP2、obtainFreshBeanFactroy()
- STEP3、prepareBeanFactory(beanFactory)
- STEP4、postProcessorBeanFactory(beanFactory)
- STEP5、invokePostProcessorBeanFactory(beanFactory)
- STEP6、registerBeanPostProcessors(beanFactory)
- STEP7、initMessageSource()
- STEP8、initApplicationEventMulticaster()
- STEP9、onRefresh()
- STEP10、registerListeners()
- STEP11、finishBeanFactoryInitialization(beanFactory)
- STEP12、finishRefresh()
- STEP13、destroyBeans()
- STEP14、resetCommonCaches()
- 八、Spring如何解析注解完成创建Bean 对象?
- 第一步:执行Spring启动流程的第5步
- 第二步:进入到invokePostProcessorBeanFactroy()方法的具体实现
- 第三步:实例化并执行所有已经注册的BeanFactoryPostProcessor beans,
- 第四步:BeanDefinitionRegistryPostProcessor 具体实现类执行postProcessBeanDefinitionRegistry()方法
一、Spring 核心概念
- IoC(核心中的核心):Inverse of Control, 控制反转,对象创建的权利由程序交给Spring框架
- DI(依赖注入):Dependency Injection, 依赖注入。在Spring框架负责创建对象时,动态的将依赖对象注入到Bean组件中
- AOP:面向切面编程。在不修改目标对象源码的情况下,增强IoC容器中的功能
- Spring容器:指的就是IoC 容器,底层也就是一个类DefaultListableBeanFactory
二、Spring 体系结构
![image.png](https://cdn.nlark.com/yuque/0/2021/png/12747730/1637906499789-6d36c014-51ef-458d-8514-e28c511d53ba.png#clientId=uba4477c3-a796-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=231&id=ub24686ce&margin=%5Bobject%20Object%5D&name=image.png&originHeight=416&originWidth=540&originalType=binary&ratio=1&rotation=0&showTitle=false&size=51329&status=done&style=none&taskId=u96b1661f-dc0d-4f5c-9732-453a1978345&title=&width=300) ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12747730/1640657958866-e6c24e3d-3418-470b-9608-4f30f5fc5a68.png#clientId=u74cee23b-ad3d-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=290&id=u2ce05a3a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=579&originWidth=463&originalType=binary&ratio=1&rotation=0&showTitle=false&size=77060&status=done&style=none&taskId=ucfab179a-964b-4fcc-bee1-de512514927&title=&width=231.5)
从上面Spring的体系结构中可以看到,Spring主要分为5大模块,一些组件都是整合在大的模块中。接下来简单介绍一下5大核心模块的功能和依赖关系。
2.1 核心容器(Core Container)
基本介绍:
Core和 Beans 模块提供了Spring最基础的功能,提供了IoC和依赖注入特性。这里的核心概念BeanFactory,它提供对Factory模式的经典实现来消除对程序性单例模式的需要,并真正地允许你从程序逻辑中分离出依赖关系和配置。
Context模块基于Core和Bean来构建,它提供了用一种框架风格地方式来访问对象,有些像JNDI注册表。Context封装包继承了beans包的功能,还增加了国际化(I18N),事件传播,资源装载,以及透明创建上下文,例如通过servlet容器,以及对大量JavaEE特性的支持,如EJB,JMX.核心接口是ApplicationContext.
Expression Language,表达式语言模块,提供了在运行期间查询和操作对象图的强大能力。支持访问和修改属性值,方法调用,支持访问及修改数组、容器和索引器,命名变量,支持算数和逻辑运算,支持从spring容器获取Bean,它也支持列表投影、选择和一般的列表聚合等。
core:
core部分包含4个模块
- spring-core:依赖注入DI与IoC的最基本实现
- spring-beans:Bean工厂与bean的装配
- spring-context:spring的context上下文即IoC容器
- spring-expression:spring表达式语言
2.2 AOP
基本概述:
aop模块,提供了符合aop联盟规范的面向切面的编程实现,让你可以定义如方法拦截器和切入点,从逻辑上讲,可以减弱代码的功能耦合,清晰地被分离开。而且,利用源码级地元数据功能,还可以将各种行为信息合并到你的代码中。 aspects模块,提供了对AspectJ的集成。 Instrumentation模块,提供一些类级的工具支持和ClassLoader级的实现,可以在一些特定的应用服务器中使用。
aop
aop部分包含4个模块
- spring-aop:面向切面编程
- spring-aspects:集成AspectJ
- spring-instrument:提供一些类级的工具支持和ClassLoader级的实现,用于服务器
- spring-instrument-tomcat:针对tomcat的instrument实现
2.3 数据访问/集成部分(Data Access/Integration)
基本概述:
JDBC模块:提供对JDBC的抽象,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码 ORM模块:提供了常用的“对象/关系”映射API的集成层。其中包括JPA、JDO、Hibernate和iBatis.利用ORM封装包,可以混合使用所有Spring提供的特性进行“对象/关系”映射,如简单声明式事务管理。 OXM模块:提供一个支持Object和XML进行映射的抽象层。其中包括JAXB、Castor、XMLBeans、JiBX和XStream. JMS模块:提供一套“消息生产者、消费者”模板用于更加简单的使用JMS,JMS用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。 Transaction模块:支持程序通过简单声明式事务管理,只要是Spring管理对象都能得到Spring管理事务的好处,即使是POJO,也可以为他们提供事务。
data access
data access部分包含5个模块
- spring-jdbc:jdbc的支持
- spring-tx:事务控制
- spring-orm:对象关系映射,集成orm框架
- spring-oxm:对象xml映射
- spring-jms:java消息服务
二、Spring 应用
常用注解
Spring中常用的注解主要分为两类: 一、使用Bean:即是把在XML中已经定义好的Bean拿来使用,完成属性、方法的组装,比如@Autowired,@Resource,可以通过byTYPE(@Autowired)、byNAME(@Resource)的方式获取Bean; 二、注册Bean: @Component , @Repository , @ Controller , @Service , @Configration这些注解都是把你要实例化的对象转化成一个Bean,放在IoC容器中,等你要用的时候,它会和上面的@Autowired@Resource配合到一起,把对象、属性、方法完美组装。
IOC注解(创建对象)
@Component
作用:
把资源交给Spring 来管理,相当于XML中的一个Bean 标签
属性:
value:
指定bean的id, 如果不指定value 属性,默认bean 的id 是当前类名,首字母小写
@Controller、@Service、@Repository
他们三个注解都是对针对@Component的衍生注解,他们的作用及属性都是一模一样的,他们只不过是定义了更加明确化的语义。
DI注解(依赖注入)
@Autowired
@Autowired默认按照类型装配(byType)
- @Autowired是由AutowiredAnnotationBeanPostProcessor 类实现的
- @Autowired 是Spring自带的注解
@Autowired 默认情况下要求对象必须存在,如果需要允许空值,可以设置他的required属于为false,@Autowired(required = false)
�@Resource
resource 默认按照名称进行装配(byName),可以通过@Resource的name属性指定名称,如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查询,当找不到与名称匹配的bean后按照类型进行装配
- 但是需要注意的是,name属性一旦指定,就将按照名称装配,不会按照类型进行装配
推荐使用这个注解,因为它属于J2EE的,减少了与Spring的耦合,这样代码看起来比较优雅。
@Inject
是根据类型进行装配的,如果需要按照名称进行装配就需要和@Named配合使用
- inject 是JSR330 中的规范,需要导入javax.inject.Inject; 实现注入
-
@Value
给基本类型和String注入属性值
- 可以使用占位符获取属性文件中的值
@Value("${name}")
private String name;
@Qualifier
@Autowired、@Inject、@Resource 三者区别
- Autowired 是Spring的注解,Inject和Resource 非Sping注解需要导入其他包
- Autowired 和 Inject 用法基本一样,区别的是 Autowired 多一个属性 required
- Autowired 和 Inject 都是按照类型进行装配,Resource按照名称进行装配
- Autowired 如果需要按照名称装配需要和Qualifier配合使用,Inject 需要和Named 配合使用
生命周期相关注解
@PostConstruct
@PreDestory系统配置注解
@Configuration
相当于Spring 中的XML配置文件
从Spring3.0开始可以使用Configuration定义配置类,可替换xml配置文件
配置类内部包含一个或多个被@Bean注解定义的方法,这些类被AnnotationConfigApplicationContext和
AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean 对象,初始化IOC容器
属性
value:用于指定配置类的字节码文件
代码示例
Spring容器初始化时,会调用配置类的无参构造
@Configuration
@MapperScan(basePackages = {"com.bj58.lego.ssp.modules.base.dao.mapper",
"com.bj58.lego.ssp.modules.flowmanage.dao.mapper",
"com.bj58.lego.ssp.modules.product.mapper",
"com.bj58.lego.ssp.modules.sale.mapper",
"com.bj58.lego.ssp.modules.discount.mapper"}, sqlSessionTemplateRef = "primarySqlSessionTemplate")
public class PrimaryMpConfig {
@Bean(name = "primarySqlSessionFactory")
@Primary
public SqlSessionFactory sqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.addInterceptor(new PaginationInterceptor());
bean.setConfiguration(configuration);
bean.setDataSource(dataSource);
//bean.setPlugins(new Interceptor[]{new PaginationInterceptor()});
ArrayList<String> resourceStrs = new ArrayList<>();
resourceStrs.add("classpath*:mapper/base/*.xml");
resourceStrs.add("classpath*:mapper/sale/*.xml");
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
ArrayList<Resource> resources = new ArrayList<>();
for (String resourceStr : resourceStrs) {
resources.addAll(Arrays.asList(resourceResolver.getResources(resourceStr)));
}
bean.setMapperLocations(resources.toArray(new Resource[0]));
return bean.getObject();
}
@Bean(name = "primarySqlSessionTemplate")
@Primary
public SqlSessionTemplate primarySqlSessionTemplate(@Qualifier("primarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
@Bean
- 相当于 bean 标签
- 作用:注册bean 对象,主要用来配置非定义的bean,比如DruidDataSource
- @Bean 用在方法上(返回某个实例的方法)
属性:
name:给当前@Bean注解方法创建的对象指定一个名称(即Bean的id),如果不指定,默认和方法名相同
@ComponentScan
- 相当于context:component-sacn 标签
- 组件扫描,扫描 @Service、@Compinent、@Controller、@Repository 注解的类
- 该注解是编写在类上面的,配合@Configutation注解一起使用
属性:
basePackages: 用于指定包扫描
value: 和basePackages 作用一样
代码:
@Configuration
@ComponentScan(basePackages = "com.bj58.lego.bi.modules.*")
public class FourthMpConfig {
@Bean(name = "fourthSqlSessionFactory")
@Primary
public SqlSessionFactory sqlSessionFactory (@Qualifier("fourthDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/BiRealDataMapper.xml"));
return bean.getObject();
}
@Bean(name = "fourthSqlSessionTemplate")
@Primary
public SqlSessionTemplate primarySqlSessionTemplate (@Qualifier("fourthSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
@PropertySource
- 用在类上面,主要用于加载Properties 配置文件
属性:
value[]:用于指定properties 文件的位置,如果在类路径下,需要写上calssPath
@Import
三、Spring 重要接口
2.1 BeanFactroy继承体系
IOC和DI: 控制反转、依赖注入 IOC容器:Spring容器(Bean)———BeanFactory接口———DefaultListableBeanFactry实现类———Map数据结构存储bean
2.1.1 继承关系图
这是banFactory的整个继承体系结构图,没有包括强大的ApplicationContext体系。标红的是整个体系结构外接的其他体系结构。
beanFactory 四级接口继承体系:
- beanFactory 作为一个主接口不继承任何接口,可以看作为一级接口
- AutowireCapableBeanFactory、ListableBeanFactory、HierarchicalBeanFactory 3个子接口继承了beanFactory, 进行了功能上的增强。这三个子接口称为二级接口
- ConfigurableBeanFactory 可以称为三级接口,对二级接口HierarchicalBeanFactroy进行了再次增强,它还继承了另外一个外来的接口SignletonBeanRegistry
- ConfigurableListBeanFactory 是一个更强大的接口,它继承了所有上面的接口,无所不包,称为四级接口
总结:
|— BeanFactory: 是Sping 容器的根接口,提供获取bean、是否包含bean、是否单例与原型、获取bean类型的接口 |— — AutowireCapableBeanFactory: 提供工厂的装备功能 |— — ListableBeanFactory: 提供容器内所有bean实例的枚举功能 |— — HierarchicalBeanFactory:提供父容器的访问功能 |— — — ConfigurableBeanFactory: 提供beanFactory的装备功能
重要2个接口和2个抽象类:
- AbstractBeanFactory作为一个抽象类,实现了三级接口ConfigurableBeanFactory的大部分功能
- AbstractAutowireCapableBeanFactory 同样是抽象类,继承了AbstractBeanFactory类,实现了
AutowireCapableBeanFactory接口
- DefaultListableBeanFactory 继承自AbstractAutowireCapableBeanFactory,实现了强大的四级接口ConfigurableListBeanFactory,并实现了一个外来接口BeanDifinitionRegistry,它并非抽象类。
BeanFactory
package org.springframework.beans.factory;
public interface BeanFactory {
//用来引用一个实例,或把它和工厂产生的Bean区分开
//就是说,如果一个FactoryBean的名字为a,那么,&a会得到那个Factory
String FACTORY_BEAN_PREFIX = "&";
/** 四个不同形式的getBean方法,获取实例 */
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
// 是否存在
boolean containsBean(String name);
// 是否为单实例
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
// 是否为原型(多实例)
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
// 名称、类型是否匹配
boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;
// 获取类型
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
// 根据实例的名字获取实例的别名
String[] getAliases(String name);
}
2.2 ApplicationContext继承体系
2.2.1 类继承关系图
ApplicationContext 允许上下文嵌套,通过保持父上下文可以维持一个上下文体系。对于Bean的查找可以在这个上下文体系中发生,首先是检查上下文,其次是父上下文,逐级向上,这样为不同的Spring 应用提供了一个共享的Bean定义环境。
四、IOC 容器
一、Spring IOC 容器基本原理
- 两个核心容器—-map
Map
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
Map
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
/** Cache of singleton objects: bean name --> bean instance */
/** 一级缓存 **/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
二、Spring 容器初始化过程
2.1 主流程源码分析
2.2.1 流程入口
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
2.2.2 流程分析
AbstractApplicationContext的 refresh()方法
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// STEP 1: 刷新预处理
/**
* 1.
* 2.
* 3.
* 4.
*/
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// STEP 2: 创建并获得beanFactory
/**
* 1. AbstractRefreshableApplicationContext.refreshBeanFactory(); 预刷新 beanFactory
* a) 创建IoC容器(DefaultListableBeanFactory)
* b) 加载解析XML文件(最终存储到Document对象中)
* c) 读取Document对象,并完成BeanDefinition的加载和注册工作
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// STEP 3:对IoC容器进行一些预处理(设置一些公共属性)
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//STEP 4: 设置beanFactory 的一些属性
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//STEP 5: 调用BeanFactoryPostProcessor后置处理器对BeanDefinition处理
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//STEP 6: 注册BeanPostProcessor后置处理器
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
//STEP 7: 初始化一些消息源(比如处理国际化的i18n等消息源)
initMessageSource();
// Initialize event multicaster for this context.
//STEP 8: 初始化应用事件广播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
//STEP 9: 初始化一些特殊的bean
onRefresh();
// Check for listener beans and register them.
// STEP 10: 注册一些监听器
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// STEP 11: 实例化剩余的单例bean(非懒加载方式)
// 注意事项:Bean的IoC、DI和AOP都是发生在此步骤
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 完成Spring整个对象的创建,生成一个完整的对象
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
2.2 创建BeanFactroy流程分析
2.2.1 入口
AbstractApplicationContext类的 refresh 方法: ```java /**
- AbstractRefreshableApplicationContext.refreshBeanFactory(); 预刷新 beanFactory
- a) 创建IoC容器(DefaultListableBeanFactory)
- b) 加载解析XML文件(最终存储到Document对象中)
- c) 读取Document对象,并完成BeanDefinition的加载和注册工作
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
```
2.2.2 流程源码分析
进入AbstractBeanFactory的obtainFreshBeanFactoy()方法中:
用于创建一个新的 IoC容器 ,这个 IoC容器 就是DefaultListableBeanFactory对象。
/**
* Tell the subclass to refresh the internal bean factory.
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 主要通过该方法创建IOC容器
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
进入AbstractRefreshableApplicationContext的 refreshBeanFactory 方法:
- 销毁以前的容器
- 创建新的容器
- 加载BeanDifinition对象到IOC容器中
```java
@Override
protected final void refreshBeanFactory() throws BeansException {
// 销毁以前的IOC容器
if (hasBeanFactory()) {
} try {destroyBeans();
closeBeanFactory();
} catch (IOException ex) {// 创建新的 IOC 容器
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 为每个容器设置一个序列化ID
beanFactory.setSerializationId(getId());
// 增强定制 beanFactory
customizeBeanFactory(beanFactory);
// 加载BeanDefinition 对象, 并注册到IOC容器中(重点)
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} }throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
- **进入到AbstractRefreshableApplicationContext的createBeanFactory**
```java
// 返回 DefaultListableBeanFactory 对象, 真正的IOC容器
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
2.4 加载BeanDifinition流程分析
2.4.1 入口
- AbstractRefreshableApplicationContext类的 refreshBeanFactory 方法中第13行代码 loadBeanDefinition()
@Override
protected final void refreshBeanFactory() throws BeansException {
// 销毁以前的IOC容器
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建新的 IOC 容器
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 为每个容器设置一个序列化ID
beanFactory.setSerializationId(getId());
// 增强定制 beanFactory
customizeBeanFactory(beanFactory);
// 加载BeanDefinition 对象, 并注册到IOC容器中(重点)
// 加载 beanDefinition 的入口
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
2.4.2 流程图
loadBeanDefinitions() 时序图:
loadBeanDefinitions() 方法变化过程图:
2.4.3 流程相关的类说明
- AbstractRefreshableApplicationContext
主要用来为beanFactory 提供 refresh功能。主要包括:beanFactory的创建、beanDefinition定义、解析、注册等。
- AbstractXmlApplicationContext
主要提供对于 XML资源 的加载功能。包括从Resource资源对象和资源路径中加载XML文件。
AbstractBeanDefinitionReader
主要提供对于 BeanDefinition 对象的读取功能。具体读取工作交给子类实现。
XmlBeanDefinitionReader
主要通过 DOM4J 对于 XML资源 的读取、解析功能,并提供对于 BeanDefinition 的注册功能。
DefaultBeanDefinitionDocumentReader
-
2.4.4 流程源码分析
AbstractRefreshableApplicationContext 类的 138 进行调用loadBeanDefinitions(beanFactory)
@Override
protected final void refreshBeanFactory() throws BeansException {
// 销毁以前的IOC容器
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建新的 IOC 容器
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 为每个容器设置一个序列化ID
beanFactory.setSerializationId(getId());
// 增强定制 beanFactory
customizeBeanFactory(beanFactory);
// 加载BeanDefinition 对象, 并注册到IOC容器中(重点)
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
AbstractXmlApplicationContext 类的 loadBeanDefinitions(BeanFactory)
- 创建一个xml的beanDefinitionReader,并通过回调设置到beanFactory中
- 给reader 对象设置环境
- 初始化 beanDifinitionReader 对象,设置配置文件是否要进行验证
开始完成beanDifiniton的加载
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
// 1.创建一个xml的beanDefinitionReader,并通过回调设置到beanFactory中
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
//2. 给reader 对象设置环境
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
// 3. 初始化 beanDifinitionReader 对象,设置配置文件是否要进行验证
initBeanDefinitionReader(beanDefinitionReader);
// 4. 开始完成beanDifiniton的加载
loadBeanDefinitions(beanDefinitionReader);
}
AbstractXmlApplicationContext 类的 loadBeanDefinitions(XmlBeanDefinitionReader)
- 获取资源配置,默认为空
- 获取资源路径,得到String[], 注意此处的 getConfigLocations(),在refresh()流程中有过setConfigLocation() 方法,其实两者是相互对应的
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
AbstractBeanDefinitionReader 类的 loadBeanDefinitions(String… locations)
- for循环处理得到的 String[] 资源位置
```java
@Override
public int loadBeanDefinitions(String… locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, “Location array must not be null”);
int counter = 0;
for (String location : locations) {
} return counter; }counter += loadBeanDefinitions(location);
- for循环处理得到的 String[] 资源位置
```java
@Override
public int loadBeanDefinitions(String… locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, “Location array must not be null”);
int counter = 0;
for (String location : locations) {
- **AbstractBeanDefinitionReader 类的 loadBeanDefinitions(String location)**
- **根据 location 获取得到资源数据 Resource[] /Resource**
- **解析Resource 实体进行BeanDefinition的加载**
```java
// Load bean definitions from the specified resource location.
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
// 获取资源加载器
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
// 通过location 获取得到资源 Resource[]
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
// 解析resource 然后加载BeanDefinition
int loadCount = loadBeanDefinitions(resources);
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// Can only load single resources by absolute URL.
// 通过location 获取得到资源 Resource
Resource resource = resourceLoader.getResource(location);
// 解析resource 然后加载BeanDefinition
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
}
}
- BeanDefinitionReader 类的 loadBeanDefinitions(Resource resource)
- 该类是一个抽象类,由具体的实现类进行解析读取到的 resource
XmlBeanDefinitionReader 类的 loadBeanDefinitions(EncodedResource encodedResource)
- 真正的解析读取资源,得到输入流 InputStream (所谓的资源一般是指xml 等配置文件)
执行最核心的加载beanDefinition方法 doLoadBeanDefinitions() ```java // Load bean definitions from the specified XML file. public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { Assert.notNull(encodedResource, “EncodedResource must not be null”); if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource);
}
Set
currentResources = this.resourcesCurrentlyBeingLoaded.get(); if (currentResources == null) { currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
} if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
} try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
// STEP 1: 解析读取XML文件得到输入流
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// STEP 2:执行最核心的加载beanDefinition方法
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
} catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
} finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
} }
- **XmlBeanDefinitionReader 类中的 doLoadBeanDefinition()方法**
- **读取资源输入流生成java 程序可以解析的 Document**
- **解析Document 进行beanDefiniiton的真正注册流程**
```java
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 根据资源输入流创建 Document,
Document doc = doLoadDocument(inputSource, resource);
// 解析Java 程序可以解析的 doc 文档注册beanDefinition
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
......
}
}
XmlBeanDefinitionReade 类中的 registerBeanDefinitions(doc, resource)
- 通过beanUtils 创建 BeanDefinitionDocumentReade 对象
- 调用获取 DefaultListbaleBeanFactory 中的 beanDefinitionMap 大小
- 解析Document 进行 BeanDefiniiton 注册
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// 使用 BeanUtils 创建 BeanDefinitionDocumentReader 对象
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// 获取 得到 BeanDefinitionRegistry,然后获取 DefaultListableBeanFactory 中 beanDefinitionMap 大小
int countBefore = getRegistry().getBeanDefinitionCount();
// 解析document文档 然后注册到容器中
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
DefaultBeanDefinitionDoucntmentReader 类的 registerBeanDefinitions() ```java @Override public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
} /**
Register each bean definition within the given root {@code
} element. / //任何嵌套的元素都将在此方法中导致递归。为了正确传播和保留 default-属性,请跟踪当前(父)委托,该委托可能为空。 //创建一个新的(子)委托,其中包含一个对父委托的引用,用于回退的目的,然后最终将this.delegate重置回其原始(父)引用。 //这种行为模拟了一堆委托,但实际上并不需要委托。 protected void doRegisterBeanDefinitions(Element root) { // Any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one.
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
- **DefaultBeanDefinitionDoucntmentReader 类的 doRegisterBeanDefinition()**
```java
/**
* Register each bean definition within the given root {@code <beans/>} element.
*/
protected void doRegisterBeanDefinitions(Element root) {
// Any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one.
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
DefaultBeanDefinitionDoucntmentReader 类的 createDelegate() ```java protected BeanDefinitionParserDelegate createDelegate(
XmlReaderContext readerContext, Element root, @Nullable BeanDefinitionParserDelegate parentDelegate) {
BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
delegate.initDefaults(root, parentDelegate);
return delegate;
}
- ** BeanDefinitionParserDelegate类的 initDefaults()方法**
```java
/**
* Initialize the default lazy-init, autowire, dependency check settings,
* init-method, destroy-method and merge settings. Support nested 'beans'
* element use cases by falling back to the given parent in case the
* defaults are not explicitly set locally.
* @see #populateDefaults(DocumentDefaultsDefinition, DocumentDefaultsDefinition, org.w3c.dom.Element)
* @see #getDefaults()
*/
public void initDefaults(Element root, @Nullable BeanDefinitionParserDelegate parent) {
populateDefaults(this.defaults, (parent != null ? parent.defaults : null), root);
this.readerContext.fireDefaultsRegistered(this.defaults);
}
BeanDefinitionParserDelegate 类的parseBeanDefinitions() 方法
/**
* Parse the elements at the root level in the document:
* "import", "alias", "bean".
* @param root the DOM root element of the document
*/
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
2.5 Bean 实例化分析
Spring 的核心模块,bean 的实例化和初始化两个过程。
2.5.1 入口
AbstractApplicationContext类的 refresh 方法:
// Instantiate all remaining (non-lazy-init) singletons.
// STEP 11: 实例化剩余的单例bean(非懒加载方式)
// 注意事项:Bean的IoC、DI和AOP都是发生在此步骤
finishBeanFactoryInitialization(beanFactory);
AbstractApplicationContext类的 finishBeanFactoryInitialization 方法:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
2.5.2 源码流程分析
AbstractApplicationContext 类的 finishBeanFactoryInitialization()
- 为上下文初始化类型转换器(核心类:ConversionService)
- 设置默认值解析器
- AOP相关内容
实例化单例Bean
/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 为上下文初始化类型转换器
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
// 如果beanFactory 之前没有注册嵌入值解析器,则注册默认的嵌入值解析器,主要用于注解属性值的解析
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
// 实例化前禁止修改bean 中的属性,允许缓存但是不允许改变
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 实例化单例bean
beanFactory.preInstantiateSingletons();
}
DefaultListableBeanFactory 类中的 preInstantiateSingletons()方法
- 从解析好的BeanDefinition集合中获取需要进行初始化的对象
通过 getBean()方法中的流程进行bean 实例的初始化,注意区分 beanFactory 和FactoryBean 两种实例化方式都会在这里发生,但是具体的方式是不同的
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isDebugEnabled()) {
logger.debug("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
// 将所有的BeanDefinition的名称创建一个集合
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
// 触发所有非延迟加载单例bean 的初始化,遍历集合对象
for (String beanName : beanNames) {
// 合并父类 BeanDefinition
// 判断缓存中是否存在,如果存在直接返回,不存在创建 RootBeanDefinition()
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 条件判断 抽象、单列、懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// FactoryBean & BeanFactory
// 1. 都是对象工厂, 用来创建对象
// 2. 如果使用BeanFactory的接口,那么必须要严格遵守Spring bean 的生命周期,从实例化到初始化,到后面的一系列方法都必须执行
// 3. 创建的对象都会交给Spring来管理: beanFactory 创建的对象会放入一级缓存 singltonObjects; FactoryBean 创建对象放入了 factoryBeanObjectCache中
// 4. 如果不是单列的话,那么需要每次调用的时候重新创建,缓存中不会保存当前对象
// 如果需要一种更加便捷的方式创建,所以就有了FactoryBean, 不需要遵守Spring bean 的生命周期;甚至可以在里面通过 new 创建对象
// 当使用 FactoryBean 接口来创建对象的时候,一共创建了2个对象
// 1. 实现了factoryBean 接口的子类对象 2. 通过getObject方法返回的对象
// 判断是否实现了factoryBean 接口
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
}
2.6 获取bean流程(实例对象流程)
2.7 调用后置处理器解析BeanDefiniiton(invokeBeanFactoryPostProcessors)
13个方法中的 invokeBeanFactoryPostProcessors方法
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
........
try {
// Allows post-processing of the bean factory in context subclasses.
// 子类覆盖方法做额外的处理,此处我们自己一般不做任何扩展工作,但是可以查看web中的代码,是有具体实现的
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 调用各种beanFactory处理器
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册bean处理器,这里只是注册功能,真正调用的是getBean方法
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 为上下文初始化message源,即不同语言的消息体,国际化处理,在springmvc的时候通过国际化的代码重点讲
initMessageSource();
........
}
........
}
AbstractApplicationContext类中的 invokeBeanFactoryPostProcessors方法
/**
* 实例化并且调用所有已经注册了的beanFactoryPostProcessor,遵循指明的顺序
*
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before singleton instantiation.
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 获取到当前应用程序上下文的beanFactoryPostProcessors变量的值,并且实例化调用执行所有已经注册的beanFactoryPostProcessor
// 默认情况下,通过getBeanFactoryPostProcessors()来获取已经注册的BFPP,但是默认是空的,那么问题来了,如果你想扩展,怎么进行扩展工作?
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()));
}
}
PostProcessorRegistrationDelegate 类中的 invokeBeanFactoryPostProcessors() 方法
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
// 无论是什么情况,优先执行BeanDefinitionRegistryPostProcessors
// 将已经执行过的BFPP存储在processedBeans中,防止重复执行
Set<String> processedBeans = new HashSet<>();
// 判断beanfactory是否是BeanDefinitionRegistry类型,此处是DefaultListableBeanFactory,实现了BeanDefinitionRegistry接口,所以为true
if (beanFactory instanceof BeanDefinitionRegistry) {
// 类型转换
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 此处希望大家做一个区分,两个接口是不同的,BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子集
// BeanFactoryPostProcessor主要针对的操作对象是BeanFactory,而BeanDefinitionRegistryPostProcessor主要针对的操作对象是BeanDefinition
// 存放BeanFactoryPostProcessor的集合
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// 存放BeanDefinitionRegistryPostProcessor的集合
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 首先处理入参中的beanFactoryPostProcessors,遍历所有的beanFactoryPostProcessors,将BeanDefinitionRegistryPostProcessor
// 和BeanFactoryPostProcessor区分开
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
// 如果是BeanDefinitionRegistryPostProcessor
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
// 直接执行BeanDefinitionRegistryPostProcessor接口中的postProcessBeanDefinitionRegistry方法
registryProcessor.postProcessBeanDefinitionRegistry(registry);
// 添加到registryProcessors,用于后续执行postProcessBeanFactory方法
registryProcessors.add(registryProcessor);
} else {
// 否则,只是普通的BeanFactoryPostProcessor,添加到regularPostProcessors,用于后续执行postProcessBeanFactory方法
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<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 调用所有实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor实现类
// 找到所有实现BeanDefinitionRegistryPostProcessor接口bean的beanName
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 遍历处理所有符合规则的postProcessorNames
for (String ppName : postProcessorNames) {
// 检测是否实现了PriorityOrdered接口
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 获取名字对应的bean实例,添加到currentRegistryProcessors中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 将要被执行的BFPP名称添加到processedBeans,避免后续重复执行
processedBeans.add(ppName);
}
}
// 按照优先级进行排序操作
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 添加到registryProcessors中,用于最后执行postProcessBeanFactory方法
registryProcessors.addAll(currentRegistryProcessors);
// 遍历currentRegistryProcessors,执行postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 执行完毕之后,清空currentRegistryProcessors
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// 调用所有实现Ordered接口的BeanDefinitionRegistryPostProcessor实现类
// 找到所有实现BeanDefinitionRegistryPostProcessor接口bean的beanName,
// 此处需要重复查找的原因在于上面的执行过程中可能会新增其他的BeanDefinitionRegistryPostProcessor
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 检测是否实现了Ordered接口,并且还未执行过
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
// 获取名字对应的bean实例,添加到currentRegistryProcessors中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 将要被执行的BFPP名称添加到processedBeans,避免后续重复执行
processedBeans.add(ppName);
}
}
// 按照优先级进行排序操作
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 添加到registryProcessors中,用于最后执行postProcessBeanFactory方法
registryProcessors.addAll(currentRegistryProcessors);
// 遍历currentRegistryProcessors,执行postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 执行完毕之后,清空currentRegistryProcessors
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// 最后,调用所有剩下的BeanDefinitionRegistryPostProcessors
boolean reiterate = true;
while (reiterate) {
reiterate = false;
// 找出所有实现BeanDefinitionRegistryPostProcessor接口的类
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 遍历执行
for (String ppName : postProcessorNames) {
// 跳过已经执行过的BeanDefinitionRegistryPostProcessor
if (!processedBeans.contains(ppName)) {
// 获取名字对应的bean实例,添加到currentRegistryProcessors中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 将要被执行的BFPP名称添加到processedBeans,避免后续重复执行
processedBeans.add(ppName);
reiterate = true;
}
}
// 按照优先级进行排序操作
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 添加到registryProcessors中,用于最后执行postProcessBeanFactory方法
registryProcessors.addAll(currentRegistryProcessors);
// 遍历currentRegistryProcessors,执行postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 执行完毕之后,清空currentRegistryProcessors
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 调用所有BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 最后,调用入参beanFactoryPostProcessors中的普通BeanFactoryPostProcessor的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
} else {
// Invoke factory processors registered with the context instance.
// 如果beanFactory不归属于BeanDefinitionRegistry类型,那么直接执行postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 到这里为止,入参beanFactoryPostProcessors和容器中的所有BeanDefinitionRegistryPostProcessor已经全部处理完毕,下面开始处理容器中
// 所有的BeanFactoryPostProcessor
// 可能会包含一些实现类,只实现了BeanFactoryPostProcessor,并没有实现BeanDefinitionRegistryPostProcessor接口
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// 找到所有实现BeanFactoryPostProcessor接口的类
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 用于存放实现了PriorityOrdered接口的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
// 用于存放实现了Ordered接口的BeanFactoryPostProcessor的beanName
// List<String> orderedPostProcessorNames = new ArrayList<>();
List<BeanFactoryPostProcessor> orderedPostProcessor = new ArrayList<>();
// 用于存放普通BeanFactoryPostProcessor的beanName
// List<String> nonOrderedPostProcessorNames = new ArrayList<>();
List<BeanFactoryPostProcessor> nonOrderedPostProcessorNames = new ArrayList<>();
// 遍历postProcessorNames,将BeanFactoryPostProcessor按实现PriorityOrdered、实现Ordered接口、普通三种区分开
for (String ppName : postProcessorNames) {
// 跳过已经执行过的BeanFactoryPostProcessor
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
// 添加实现了PriorityOrdered接口的BeanFactoryPostProcessor到priorityOrderedPostProcessors
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
// 添加实现了Ordered接口的BeanFactoryPostProcessor的beanName到orderedPostProcessorNames
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
// orderedPostProcessorNames.add(ppName);
orderedPostProcessor.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
} else {
// 添加剩下的普通BeanFactoryPostProcessor的beanName到nonOrderedPostProcessorNames
// nonOrderedPostProcessorNames.add(ppName);
nonOrderedPostProcessorNames.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
// 对实现了PriorityOrdered接口的BeanFactoryPostProcessor进行排序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 遍历实现了PriorityOrdered接口的BeanFactoryPostProcessor,执行postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
// 创建存放实现了Ordered接口的BeanFactoryPostProcessor集合
// List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
// 遍历存放实现了Ordered接口的BeanFactoryPostProcessor名字的集合
// for (String postProcessorName : orderedPostProcessorNames) {
// 将实现了Ordered接口的BeanFactoryPostProcessor添加到集合中
// orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
// }
// 对实现了Ordered接口的BeanFactoryPostProcessor进行排序操作
// sortPostProcessors(orderedPostProcessors, beanFactory);
sortPostProcessors(orderedPostProcessor, beanFactory);
// 遍历实现了Ordered接口的BeanFactoryPostProcessor,执行postProcessBeanFactory方法
// invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessor, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
// 最后,创建存放普通的BeanFactoryPostProcessor的集合
// List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
// 遍历存放实现了普通BeanFactoryPostProcessor名字的集合
// for (String postProcessorName : nonOrderedPostProcessorNames) {
// 将普通的BeanFactoryPostProcessor添加到集合中
// nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
// }
// 遍历普通的BeanFactoryPostProcessor,执行postProcessBeanFactory方法
// invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(nonOrderedPostProcessorNames, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
// 清除元数据缓存(mergeBeanDefinitions、allBeanNamesByType、singletonBeanNameByType)
// 因为后置处理器可能已经修改了原始元数据,例如,替换值中的占位符
beanFactory.clearMetadataCache();
}
调用BeanDefinitionRegistryPostProcessor 类的postProcessBeanDefinitionRegistry()方法
- BeanDefinitionRegistryPostProcessor 类继承了BeanFactoryPostProcessor
- 具体的方法有具体的实现类 ConfigurationClassPostProcessor 类去执行
此流程总出现了最核心的后置处理器ConfigurationClassPostProcessor类
/**
* 定位、加载、解析、注册相关注解
*
* Derive further bean definitions from the configuration classes in the registry.
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// 根据对应的registry对象生成hashcode值,此对象只会操作一次,如果之前处理过则抛出异常
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
// 将马上要进行处理的registry对象的id值放到已经处理的集合对象中
this.registriesPostProcessed.add(registryId);
// 处理配置类的bean定义信息
processConfigBeanDefinitions(registry);
}
ConfigurationClassPostProcessor 类中的processConfigBeanDefinition(BeanDefinitionRegistry)方法执行
- 从DefaultListableBeanFactory 容器中获取所有的beanDefinitionNames,通过名称获取BeanDefinition对象
- 循环遍历 BeanDefiniiton对象是否被@Configuration 注解修饰
- 先判断是否被@Configuration 注解修饰
主流程代码:
/**
* 构建和验证一个类是否被@Configuration修饰,并做相关的解析工作
*
* 如果你对此方法了解清楚了,那么springboot的自动装配原理就清楚了
*
* Build and validate a configuration model based on the registry of
* {@link Configuration} classes.
*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
// 创建存放BeanDefinitionHolder的对象集合
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
// 当前registry就是DefaultListableBeanFactory,获取所有已经注册的BeanDefinition的beanName
String[] candidateNames = registry.getBeanDefinitionNames();
// 遍历所有要处理的beanDefinition的名称,筛选对应的beanDefinition(被注解修饰的)
for (String beanName : candidateNames) {
// 获取指定名称的BeanDefinition对象
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// 如果beanDefinition中的configurationClass属性不等于空,那么意味着已经处理过,输出日志信息
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
// 判断当前BeanDefinition是否是一个配置类,并为BeanDefinition设置属性为lite或者full,此处设置属性值是为了后续进行调用
// 如果Configuration配置proxyBeanMethods代理为true则为full
// 如果加了@Bean、@Component、@ComponentScan、@Import、@ImportResource注解,则设置为lite
// 如果配置类上被@Order注解标注,则设置BeanDefinition的order属性值
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
// 添加到对应的集合对象中
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
// 如果没有发现任何配置类,则直接返回
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
// 如果适用,则按照先前确定的@Order的值排序
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
// 判断当前类型是否是SingletonBeanRegistry类型
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
// 类型的强制转换
sbr = (SingletonBeanRegistry) registry;
// 判断是否有自定义的beanName生成器
if (!this.localBeanNameGeneratorSet) {
// 获取自定义的beanName生成器
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
// 如果有自定义的命名生成策略
if (generator != null) {
//设置组件扫描的beanName生成策略
this.componentScanBeanNameGenerator = generator;
// 设置import bean name生成策略
this.importBeanNameGenerator = generator;
}
}
}
// 如果环境对象等于空,那么就重新创建新的环境对象
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
// 实例化ConfigurationClassParser类,并初始化相关的参数,完成配置类的解析工作
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// 创建两个集合对象,
// 存放相关的BeanDefinitionHolder对象
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
// 存放扫描包下的所有bean
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
// 解析带有@Controller、@Import、@ImportResource、@ComponentScan、@ComponentScans、@Bean的BeanDefinition
parser.parse(candidates);
// 将解析完的Configuration配置类进行校验,1、配置类不能是final,2、@Bean修饰的方法必须可以重写以支持CGLIB
parser.validate();
// 获取所有的bean,包括扫描的bean对象,@Import导入的bean对象
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
// 清除掉已经解析处理过的配置类
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
// 判断读取器是否为空,如果为空的话,就创建完全填充好的ConfigurationClass实例的读取器
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// 核心方法,将完全填充好的ConfigurationClass实例转化为BeanDefinition注册入IOC容器
this.reader.loadBeanDefinitions(configClasses);
// 添加到已经处理的集合中
alreadyParsed.addAll(configClasses);
candidates.clear();
// 这里判断registry.getBeanDefinitionCount() > candidateNames.length的目的是为了知道reader.loadBeanDefinitions(configClasses)这一步有没有向BeanDefinitionMap中添加新的BeanDefinition
// 实际上就是看配置类(例如AppConfig类会向BeanDefinitionMap中添加bean)
// 如果有,registry.getBeanDefinitionCount()就会大于candidateNames.length
// 这样就需要再次遍历新加入的BeanDefinition,并判断这些bean是否已经被解析过了,如果未解析,需要重新进行解析
// 这里的AppConfig类向容器中添加的bean,实际上在parser.parse()这一步已经全部被解析了
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
// 如果有未解析的类,则将其添加到candidates中,这样candidates不为空,就会进入到下一次的while的循环中
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
判断是否被注解修饰流程
- **判断是否被@Configuration 修饰**
if (isFullConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
public static boolean isFullConfigurationCandidate(AnnotationMetadata metadata) {
return metadata.isAnnotated(Configuration.class.getName());
}
- **如果没有,判断@Import、@ImportResource、@ComponentScan、@ComponentScans**
- **如果没有,判断 @Bean **
public static boolean isLiteConfigurationCandidate(AnnotationMetadata metadata) {
// Do not consider an interface or an annotation...
if (metadata.isInterface()) {
return false;
}
// Any of the typical annotations found?
for (String indicator : candidateIndicators) {
if (metadata.isAnnotated(indicator)) {
return true;
}
}
// Finally, let's look for @Bean methods...
try {
return metadata.hasAnnotatedMethods(Bean.class.getName());
}
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
}
return false;
}
}
五、AOP
AOP-面向切面编程
一、AOP设计原理
1.1 Java 程序在JVM 中运行特征
当我们在某个类中写了一个main()方法,然后开始执行程序,整个程序完成运行。如下:
public static void main(String[] args) {
String result = new BCryptPasswordEncoder().encode("lego_bi");
System.out.println(result);
}
那么在这个执行的工程中,JVM 做了什么?
当我们执行程序的时候,JVM 会创建一个主线程main,这个主线程将以上述的main()方法作为入口,开始执行代码。每个线程在自己的内在中维护着属于自己的栈(Stack),记录着整个程序的运行过程。栈里的每个元素被称为栈帧(Stack Frame),栈帧表示着某个方法调用,会记录方法调用的信息;实际上我们在代码中调用一个方法的时候,在内存中就对应着一个栈帧的入栈和出栈。
在某个特定的时间范围内,一个Main 线程中的栈变化情况如下图:
从线程栈的角度来看,我们可以看到,JVM处理Java程序的基本单位是方法调用。实际上,JVM执行的最基本单位的指令(即原子操作)是汇编语言性质的机器字节码。这里之所以讲方法调用时Java程序的基本执行单位,是从更宏观的角度看待的。
1.2 Java 程序执行流【了解AOP 中的连接点(Join point)、切入点(point cut) 的概念】
如果从虚拟机栈角度考虑Java 程序执行的话,我们会发现,整个程序执行就是方法调用的过程。将方法执行的顺序,将方法调用排成一排,这样就构成了Java 程序执行流。
我们将Java 程序执行流简单画个图如下:
基于时间序列,我们可以将方法调用排成一条线。而每个方法调用则可以看成Java执行流中的一个节点。这个节点在AOP的术语中,被称为Join Point,即连接点。 一个Java程序的运行的过程,就是若干个连接点连接起来依次执行的过程。
在我们正常的面向对象的思维中, 我们考虑的是如何按照时间序列通过方法调用来实现我们的业务逻辑。那么,什么是AOP(即面向切面的编程)呢?
通常面向对象的程序,代码都是按照时间序列纵向展开的,而他们都有一个共性:即都是已方法调用作为基本执行单位展开的。 将方法调用当做一个连接点,那么由连接点串起来的程序执行流就是整个程序的执行过程。
AOP(Aspect Oriented Programming)则是从另外一个角度来考虑整个程序的,AOP将每一个方法调用,即连接点作为编程的入口,针对方法调用进行编程。从执行的逻辑上来看,相当于在之前纵向的按照时间轴执行的程序横向切入。相当于将之前的程序横向切割成若干的面,即Aspect.每个面被称为切面。 所以,根据我的理解,AOP本质上是针对方法调用的编程思路。
![image.png](https://cdn.nlark.com/yuque/0/2021/png/12747730/1638325409552-b02f61c9-8967-43ba-b985-4f3c9aa24fb7.png#clientId=uc7864c60-66a5-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=414&id=uf4ae8215&margin=%5Bobject%20Object%5D&name=image.png&originHeight=827&originWidth=693&originalType=binary&ratio=1&rotation=0&showTitle=false&size=241008&status=done&style=none&taskId=uccc51af3-f56b-41f2-aed5-b7a1f8f99c0&title=&width=346.5)
既然AOP是针对切面进行的编程的,那么,你需要选择哪些切面(即 连接点Joint Point)作为你的编程对象呢?
因为切面本质上是每一个方法调用,选择切面的过程实际上就是选择方法的过程。那么,被选择的切面(Aspect)在AOP术语里被称为切入点(Point Cut). 切入点实际上也是从所有的连接点(Join point)挑选自己感兴趣的连接点的过程。
![image.png](https://cdn.nlark.com/yuque/0/2021/png/12747730/1638326480637-af622aa7-6a9d-4d95-850e-8d326e9ec724.png#clientId=uc7864c60-66a5-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=362&id=ub3f99c30&margin=%5Bobject%20Object%5D&name=image.png&originHeight=723&originWidth=688&originalType=binary&ratio=1&rotation=0&showTitle=false&size=205666&status=done&style=none&taskId=ua3d28851-641d-4c1a-b49d-eda8c471beb&title=&width=344)
1.3 引入代理模式的Java程序执行流(AOP实现的机制)
假设我们在我们的Java 代码里,都为实例对象通过代理模式创建了代理对象,访问这些实例对象必须通过代理,那么加入代理对象的Java程序执行流比较复杂一点
由上图可以看出,只要想调用某一个实例对象的方法时,都会经过这个实例对象相对应的代理对象, 即执行的控制权先交给代理对象。
关于代理模式:
加入了代理模式的Java程序执行流,使得所有的方法调用都经过了代理对象。对于Spring AOP框架而言,它负责控制着真个容器内部的代理对象。当我们调用了某一个实例对象的任何一个非final的public方法时,整个Spring框架都会知晓。
此时的SpringAOP框架在某种程度上扮演着一个上帝的角色:它知道你在这个框架内所做的任何操作,你对每一个实例对象的非final的public方法调用都可以被框架察觉到!
![image.png](https://cdn.nlark.com/yuque/0/2021/png/12747730/1638327232209-8cbaaa46-d0d6-4f35-8cea-7d18d3e96ceb.png#clientId=uc7864c60-66a5-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=419&id=uf10809a1&margin=%5Bobject%20Object%5D&name=image.png&originHeight=837&originWidth=648&originalType=binary&ratio=1&rotation=0&showTitle=false&size=190573&status=done&style=none&taskId=u4869dcf4-7e44-46e7-a49b-918503a5c05&title=&width=324)
1.4 AOP的工作原理
AOP编程首先要选择它感兴趣的连接点——即切入点(Point cut),那么,AOP能对切入点做什么样的编程呢? 我们先将代理模式下的某个连接点细化,你会看到如下这个示意图所表示的过程:
AOP 工作原理
AOP 的核心主要分为三部分:
1. 哪些类需要进行相关的切入
expression (表达式来找到切入的类) ----->pointCut
2. 增强的逻辑处理,有几个通知消息或者说哪些逻辑可以被执行
before、after、afterThrowing、afterReturing、around ----> advisor ---> advice
3. 增强的处理逻辑类是那个,也就是那个切面
aspect
![image.png](https://cdn.nlark.com/yuque/0/2021/png/12747730/1638327581292-8e532878-c1e2-4e0e-9781-ea3f489f6e9b.png#clientId=uc7864c60-66a5-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=451&id=u8c4c63f5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=902&originWidth=804&originalType=binary&ratio=1&rotation=0&showTitle=false&size=447119&status=done&style=none&taskId=u52496ca1-acb5-4530-b5de-68cbebf5d1c&title=&width=402)
AOP 面向切面编程机制
![image.png](https://cdn.nlark.com/yuque/0/2021/png/12747730/1638327684198-786b7015-ccf9-4259-aeac-9dbd15809c99.png#clientId=uc7864c60-66a5-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=489&id=ub1f7a099&margin=%5Bobject%20Object%5D&name=image.png&originHeight=978&originWidth=811&originalType=binary&ratio=1&rotation=0&showTitle=false&size=299921&status=done&style=none&taskId=ubeb2bb20-dd56-49cb-aaa4-0fb7744f633&title=&width=405.5)
二、AOP实现原理
三、源码分析
aop 相关类继承体系
三个核心类继承关系
![image.png](https://cdn.nlark.com/yuque/0/2021/png/12747730/1638621809874-52c407c1-59fc-4e75-b06c-8f68f34e5094.png#clientId=uab9bf88d-07bf-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=266&id=ua4d46ad1&margin=%5Bobject%20Object%5D&name=image.png&originHeight=532&originWidth=1103&originalType=binary&ratio=1&rotation=0&showTitle=false&size=55312&status=done&style=none&taskId=ue3a90945-d5a3-4e1d-897b-7a116939eac&title=&width=551.5)
advice 相关类
![image.png](https://cdn.nlark.com/yuque/0/2021/png/12747730/1638623465306-dcbc3b30-97f4-4f08-bd9d-47da19b56868.png#clientId=uab9bf88d-07bf-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=92&id=u58ffe6da&margin=%5Bobject%20Object%5D&name=image.png&originHeight=183&originWidth=1054&originalType=binary&ratio=1&rotation=0&showTitle=false&size=17270&status=done&style=none&taskId=u0289bff7-e3a7-47da-842c-c654e0723bc&title=&width=527)
-
3.1 AOP 的BeanDefinition的准备工作
AbstractAutouwireCapableBeanFactory 类中的 createBean() 方法中的resolveBeforeInstantiation()方法
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
/** Strategy for creating bean instances */
// 初始化策略
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
/** Resolver strategy for method parameter names */
@Nullable
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
/** Whether to automatically try to resolve circular references between beans */
private boolean allowCircularReferences = true;
/**
* Whether to resort to injecting a raw bean instance in case of circular reference,
* even if the injected bean eventually got wrapped.
*/
private boolean allowRawInjectionDespiteWrapping = false;
/**
* Dependency types to ignore on dependency check and autowire, as Set of
* Class objects: for example, String. Default is none.
*/
private final Set<Class<?>> ignoredDependencyTypes = new HashSet<>();
/**
* Dependency interfaces to ignore on dependency check and autowire, as Set of
* Class objects. By default, only the BeanFactory interface is ignored.
*/
private final Set<Class<?>> ignoredDependencyInterfaces = new HashSet<>();
/**
* The name of the currently created bean, for implicit dependency registration
* on getBean etc invocations triggered from a user-specified Supplier callback.
*/
private final NamedThreadLocal<String> currentlyCreatedBean = new NamedThreadLocal<>("Currently created bean");
/** Cache of unfinished FactoryBean instances: FactoryBean name to BeanWrapper */
private final ConcurrentMap<String, BeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<>(16);
/** Cache of filtered PropertyDescriptors: bean Class to PropertyDescriptor array */
private final ConcurrentMap<Class<?>, PropertyDescriptor[]> filteredPropertyDescriptorsCache =
new ConcurrentHashMap<>(256);
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 给BeanPostProcessors一个机会来返回代理来真正的实例,应用实例化的前置处理器
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
}
resolveBeforeInstantiation() 方法中的applyBeanPostProcessorsBeforeInstantiation() 方法
/**
* Apply before-instantiation post-processors, resolving whether there is a
* before-instantiation shortcut for the specified bean.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @return the shortcut-determined bean instance, or {@code null} if none
*/
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
applyBeanPostProcessorsBeforeInstantiation() 方法中的postProcessBeforeInstantiation()方法
/**
* Apply InstantiationAwareBeanPostProcessors to the specified bean definition
* (by class and name), invoking their {@code postProcessBeforeInstantiation} methods.
* <p>Any returned object will be used as the bean instead of actually instantiating
* the target bean. A {@code null} return value from the post-processor will
* result in the target bean being instantiated.
* @param beanClass the class of the bean to be instantiated
* @param beanName the name of the bean
* @return the bean object to use instead of a default instance of the target bean, or {@code null}
* @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
*/
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
postProcessBeforeInstantiation() 方法的实现类 AbstractAutoProxyCreator中的核心方法createProxy()
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
// 创建代理对象
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
�
六、事物
七、Spring 启动流程
STEP1、prepareFresh()
Prepare this context for refreshing: 刷新预处理
�
STEP2、obtainFreshBeanFactroy()
Tell the subclass to refresh the internal bean factory: 创建并获得beanFactory
主要分为两大步骤:
�1. 创建beanFactory
2. 加载解析XML文件,并完成BeanDefinition的加载和注册工作
STEP3、prepareBeanFactory(beanFactory)
STEP4、postProcessorBeanFactory(beanFactory)
STEP5、invokePostProcessorBeanFactory(beanFactory)
BeanFactroyPostProcessor 称作为 BeanFactory 增强器,也叫做后置处理器。 在Spring 的流程中,先加载完成配置文件,创建生成一个beanFactroy容器来存放BeanDefinition对象,在BeanDefinition对象被实例化的过程中可能需要对BeanDefiniton 进行增强修改,此时就需要BeanFactroyPostProssor的处理,因此这就是BeanFactroyPostProssor的基本作用。BeanFactroyPostProssor 是一个接口,里面只有一个抽象方法postProcessorBeanFactroy(), BeanFactroyPostProssor 接口有很多字接口实现,进行不同的增强操作,其中最核心的子接口就是ConfigurationClassPostProcessor类,主要解析Spring中的注解完成Bean的创建。
BFPP和BDRPP 的处理流程代码:
- 先执行用户自己添加的PostProcessor
- 然后执行实现了BeanDefinitionRegistryPostProcessor 的实现类
最后执行 实现了BeanFactoryPostProcessor的实现类
在执行三个PostProcessor 的过程中,都遵循一个规则:PriorityOrder -> order -> 无排序接口
STEP6、registerBeanPostProcessors(beanFactory)
STEP7、initMessageSource()
STEP8、initApplicationEventMulticaster()
STEP9、onRefresh()
STEP10、registerListeners()
STEP11、finishBeanFactoryInitialization(beanFactory)
STEP12、finishRefresh()
STEP13、destroyBeans()
STEP14、resetCommonCaches()
八、Spring如何解析注解完成创建Bean 对象?
一、ConfigurationClassPostProcessor入口
- AbstractApplicationContext # STEP5 invokePostProcessorBeanFactory
- PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors
- PostProcessorRegistrationDelegate # 类中的 invokeBeanFactoryPostProcessors()方法
- BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry() 方法
- 进入到BeanDefinitionRegistryPostProcessor父接口中,根据具体的实现子接口进入到具体的方法
进入到ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry() 方法中 ```java
第一步:执行Spring启动流程的第5步
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
// Invoke factory processors registered as beans in the context.
//STEP 5: 调用BeanFactoryPostProcessor后置处理器对BeanDefinition处理
// invoke: 调度执行 BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
}
}
第二步:进入到invokePostProcessorBeanFactroy()方法的具体实现
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { 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())); } }
第三步:实例化并执行所有已经注册的BeanFactoryPostProcessor beans,
BeanFactoryPostProcessor 的核心执行流程
final class PostProcessorRegistrationDelegate {
public static void invokeBeanFactoryPostProcessors(
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set
// 将两种类型区分分别添加到创建的空集合中分别处理
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
........
} }
第四步:BeanDefinitionRegistryPostProcessor 具体实现类执行postProcessBeanDefinitionRegistry()方法
/**
- 此类是一个后置处理器,主要功能是参与BeanFactory的建造,主要功能如下:
- 解析加了@Configuration的配置类
- 解析@ComponentScan扫描的包
- 解析@ComponentScans扫描的包
- 解析@Import 注解 */ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
/**
Derive further bean definitions from the configuration classes in the registry. */ @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { int registryId = System.identityHashCode(registry); if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
} if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
} this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry); } } ```
二、ConfigurationClassPostProcessor 类详解
```java /**
- 此类是一个后置处理器,主要功能是参与BeanFactory的建造,主要功能如下:
- 解析加了@Configuration的配置类
- 解析@ComponentScan扫描的包
- 解析@ComponentScans扫描的包
- 解析@Import 注解 */ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
/**
- Derive further bean definitions from the configuration classes in the registry. */ @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { int registryId = System.identityHashCode(registry); if (this.registriesPostProcessed.contains(registryId)) { throw new IllegalStateException( “postProcessBeanDefinitionRegistry already called on this post-processor against “ + registry); } if (this.factoriesPostProcessed.contains(registryId)) { throw new IllegalStateException( “postProcessBeanFactory already called on this post-processor against “ + registry); } this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry); }
/**
- Prepare the Configuration classes for servicing bean requests at runtime
- by replacing them with CGLIB-enhanced subclasses. */ @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); }
enhanceConfigurationClasses(beanFactory); beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory)); }
/**
- Build and validate a configuration model based on the registry of
- {@link Configuration} classes.
*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
// 创建存放BenDefinitionHolder 的对象集合 BeanDefinitionHolder 主要是对BeanDefinition对象对包装
List
configCandidates = new ArrayList<>(); // 当前registry就是DefaultListableBeanFactory. 获取所有已经注册对BeanDefinition的beanName String[] candidateNames = registry.getBeanDefinitionNames();
// 遍历所有需要处理的beanDefinition的名称, 进行筛选被注解修饰的beanDefinition for (String beanName : candidateNames) { BeanDefinition beanDef = registry.getBeanDefinition(beanName); if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) || ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) { if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
} } else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); } }
// Return immediately if no @Configuration classes were found if (configCandidates.isEmpty()) { return; }
// Sort by previously determined @Order value, if applicable configCandidates.sort((bd1, bd2) -> { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); return Integer.compare(i1, i2); });
// Detect any custom bean name generation strategy supplied through the enclosing application context SingletonBeanRegistry sbr = null; if (registry instanceof SingletonBeanRegistry) { sbr = (SingletonBeanRegistry) registry; if (!this.localBeanNameGeneratorSet) { BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR); if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
} } }
if (this.environment == null) { this.environment = new StandardEnvironment(); }
// Parse each @Configuration class ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set
candidates = new LinkedHashSet<>(configCandidates); Set alreadyParsed = new HashSet<>(configCandidates.size()); do { parser.parse(candidates); parser.validate(); Set
configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); configClasses.removeAll(alreadyParsed); // Read the model and create bean definitions based on its content if (this.reader == null) { this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
} this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses);
candidates.clear(); if (registry.getBeanDefinitionCount() > candidateNames.length) { String[] newCandidateNames = registry.getBeanDefinitionNames(); Set
oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames)); Set alreadyParsedClasses = new HashSet<>(); for (ConfigurationClass configurationClass : alreadyParsed) { alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
} for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
} candidateNames = newCandidateNames; } } while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) { sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry()); }
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) { // Clear cache in externally provided MetadataReaderFactory; this is a no-op // for a shared cache since it’ll be cleared by the ApplicationContext. ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache(); } }
/**
- Post-processes a BeanFactory in search of Configuration class BeanDefinitions;
- any candidates are then enhanced by a {@link ConfigurationClassEnhancer}.
- Candidate status is determined by BeanDefinition attribute metadata.
- @see ConfigurationClassEnhancer
*/
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map
configBeanDefs = new LinkedHashMap<>(); for (String beanName : beanFactory.getBeanDefinitionNames()) { BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName); if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) { if (!(beanDef instanceof AbstractBeanDefinition)) {
} else if (logger.isWarnEnabled() && beanFactory.containsSingleton(beanName)) {throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
} configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef); } } if (configBeanDefs.isEmpty()) { // nothing to enhance -> return immediately return; }logger.warn("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'.");
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer(); for (Map.Entry
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); try { // Set enhanced subclass of the user-specified bean class Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader); if (configClass != null) { Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Replacing bean definition '%s' existing class '%s' with " +
"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
}
beanDef.setBeanClass(enhancedClass);
}
} } catch (Throwable ex) { throw new IllegalStateException(“Cannot load configuration class: “ + beanDef.getBeanClassName(), ex); } } }
private static class ImportAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
private final BeanFactory beanFactory;
public ImportAwareBeanPostProcessor(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
// Inject the BeanFactory before AutowiredAnnotationBeanPostProcessor's
// postProcessPropertyValues method attempts to autowire other configuration beans.
if (bean instanceof EnhancedConfiguration) {
((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory);
}
return pvs;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (bean instanceof ImportAware) {
ImportRegistry ir = this.beanFactory.getBean(IMPORT_REGISTRY_BEAN_NAME, ImportRegistry.class);
AnnotationMetadata importingClass = ir.getImportingClassFor(bean.getClass().getSuperclass().getName());
if (importingClass != null) {
((ImportAware) bean).setImportMetadata(importingClass);
}
}
return bean;
}
}
}
<a name="B3TXh"></a>
## 三、ConfingurationClassPostProcessor 执行流程
- **PostProcessorBeanDefinitionRegistrationDelegate类 调用执行PostProcessors方法,**_**invokeBeanDefinitionRegistryPostProcessors**_
- **BeanDefinitionRegistryPostProcessor 类调用postProcessBeanDefinitionRegistry()方法,这里主要根据具体的实现类去执行子类方法**
- ConfigurationClassPostProcessor. postProcessBeanDefinitionRegistry()
- ConfigurationClassPostProcessor. processConfigBeanDefinitions(registry)
- �**ConfigurationClassPostProcessor类中的processConfigBeanDefinitions()方法核心执行**
- 获取容器中的beanName
- 根据beanNanme 获取得到BeanDefinition
- 判断BeanDefinition 是不是configurationClass, attribute 如果是就跳过操作,不是执行checkConfigurationClassCandidate() 方法
- checkConfigurationClassCandidate() 方法执行流程
- 获取beanDefiniton 对象的元数据 Metadata
- 判断每个Metadata 上只有有注解
- _candidateIndicators_.add(Component.class.getName());<br />_candidateIndicators_.add(ComponentScan.class.getName());<br />_candidateIndicators_.add(Import.class.getName());<br />_candidateIndicators_.add(ImportResource.class.getName());
- @Bean
- 根据第三步的各种判断处理,得到一个需要处理的BeanDefinitionHolder集合对象configCandidates
- 根据集合中对象中order 注解值进排序元素处理顺序
- 获取BeanName 生成策略(beanNameGenerator),即 BeanName的如何生成,没有获取到就使用默认的驼峰命名法。
- 创建ConfigurationClassParser 对象,进行解析每个Configuration 类
- 解析configCandidates 集合对象 parser.parse(candidates)
- for 循环处理每个BeanDefiniiton 对象,判断BeanDefinition 对象是什么类型的
- 根据类型传入不同的参数进行执行 parse() 方法
- processConfigurationClass()进入到解析阶段
- 获取到类资源信息,SourcClass
- 开始真正的执行解析ConfigurationClass类,doProcessConfigurationClass()
- doProcessConfigurationClass(), Spring 中核心的方法,do.....
- 解析执行各种注解
- Process any @PropertySource annotations
- Process any @ComponentScan annotations
- Process any @Import annotations
- Process any @ImportResource annotations
- Process individual @Bean methods
�
- <br />
�<br />代码流程:
```java
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}