一、BeanFactory
和FactoryBean
区别
1.1 BeanFactory
- BeanFactory是一个负责生产和管理bean的一个工厂类(接口)。
- 在Spring中,BeanFactory是IOC容器的核心接口。职责:实例化、定位、配置应用程序中的对象及简历这些对象间的依赖。
- 通过getBean()方法,传入参数 --> bean的名称或者类型,便可以从Spring容器中来获取bean。
- BeanFactory是用于访问Spring容器的根接口,是从Spring容器中获取Bean对象的基础接口,提供了IOC容器最基本的形式,给具体的IOC容器的实现提供了规范。
- BeanFactory只是个接口,并不是IOC容器的具体实现,Spring容器给出很多种BeanFactory的扩展实现。如: `DefaultListableBeanFactory`、`XmlBeanFactory`、`ApplicationContext`等。
BeanFactory的类图
- 从类图中可以看出来,我们常用的ApplicationContext就是一个BeanFactory.
- ApplicationContext接口:由BeanFactory接口派生而来,ApplicationContext包含BeanFactory的所有功能,还提供了以下更多的功能:
- 1.MessageSource:提供国际化的消息访问
- 2.资源访问,如URL和文件
- 3.事件传播
- 比较BeanFactory,通常建议优先使用ApplicationContext。
1.2 FactoryBean
1. 什么是 FactoryBean
- 和BeanFactory一样,也是一个接口
- FactoryBean是为IOC容器中的Bean的实现提供了更加灵活的方式,FactoryBean在IOC容器的基础上,给Bean的实现加上了一个简单工厂模式和装饰模式。
- Spring提供的FactoryBean工厂类接口,`用户可以通过实现该接口`,然后在 `getObject()` 方法中来灵活配置,来定制实例化Bean的逻辑。
- 从Spring3.0开始,FactoryBean开始支持反省,即接口声明改为 `FactoryBean<T>` 的形式。
- 从beanFactory及其实现类的 `getBean()`方法中获取到的Bean对象,实际上是 FactoryBean的 `getObject()`方法创建并返回的Bean对象,而不是FactoryBean本身。
2. FactoryBean的源码
public interface FactoryBean<T> {
/**
* 可以在beandefinition上设置的属性的名称,这样当不能从工厂bean类中推导出对象类型时,工厂bean就可以发出信号
*/
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
1. getObject()方法
- getObject(): 返回Bean对象
- 当通过getBean()方法获取到一个Bean时,返回的并不是xxFactoryBean本身,而是其创建的Bean对象
- 如果要获取xxFactoryBean对象本身,就在getBean()参数前面添加一个 `&`来获取,即:getBean(&BeanName);
例如:
- 从BeanFactory及其实现类的getBean()方法中获取到的Bean对象,实际上是 `FactoryBean`的`getObject()`方法创建并返回的Bean对象,而不是 `FactoryBean`本身
2. getObjectType(): 返回的是Bean的对象类型
3. isSingleton(): 是否是单例对象, true是单例, false是非单例
3. FactoryBean使用场景
- FactoryBean 用来生成某一类型Bean的实例,它最大的一个作用是:可以让我们自定义Bean的创建过程。
- 比如说:有一些同属于某一类型的Bean对象需要被创建,但是它们自己有各自的特点,我们只需要把它们的特点 `注入FactoryBean中`,就可以生产出属于该类型的实例。
4. 示例代码
实现FactoryBean,功能:用来自定义一个Bean对象(Car)的创建过程
1. 新建一个 Car实体类
/**
* @Author: codertl
* @Description:
* @Date: 2023/1/31
*/
@Data
public class Car {
/**
* 汽车品牌
*/
private String carBrand;
/**
* 汽车价格
*/
private String carPrice;
}
2. 新建一个自己的FactoryBean实现,自定义Car对象的生成过程
/**
* @Author: codertl
* @Description:
* @Date: 2023/1/31
*/
@Component
public class MyFactoryBean01 implements FactoryBean<Car> {
/**
* 当通过getBean获取一个FactoryBean时,返回的并不是FactoryBean本身,而是其创建的对象;
* 如果要获取FactoryBean对象本身,请在参数前面加一个&符号来获取。
*/
@Override
public Car getObject() throws Exception {
Car car = new Car();
car.setCarBrand("宝马");
car.setCarPrice("900000");
return car;
}
/**
* 获取对象的类型
* @return
*/
@Override
public Class<?> getObjectType() {
return Car.class;
}
/**
* 该Bean对象是否是单例模式
* @return
*/
@Override
public boolean isSingleton() {
return false;
}
}
3. 测试
调用 getBean() 获取Bean对象
package com.example;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import javax.annotation.Resource;
@SpringBootTest
class SpringSourceStudyApplicationTests {
@Autowired
private ApplicationContext applicationContext;
@Test
void test01() {
// 调用 getBean() 获取Bean对象
Object object = applicationContext.getBean("myFactoryBean01");
System.out.println("该对象的类型 = " + object);
}
}
打印结果:
获取xxxFactoryBean 对象本身
package com.example;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import javax.annotation.Resource;
@SpringBootTest
class SpringSourceStudyApplicationTests {
@Autowired
private ApplicationContext applicationContext;
@Test
void test01() {
// 调用 getBean() 参数前面添加& ,获取 MyFactoryBean01 对象本身
Object object = applicationContext.getBean("&myFactoryBean01");
System.out.println("该对象的类型 = " + object);
}
}
打印结果:
获取Car的信息
package com.example;
import com.example.pojo.Car;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import javax.annotation.Resource;
@SpringBootTest
class SpringSourceStudyApplicationTests {
@Autowired
private ApplicationContext applicationContext;
@Test
void test01() {
// 调用 getBean() 获取Bean对象
Object object = applicationContext.getBean("myFactoryBean01");
System.out.println("该对象的类型 = " + object);
// 将该Bean对象转成 Car
Car car = (Car) object;
// 打印car对象信息
System.out.println("car.getCarBrand() = " + car.getCarBrand());
System.out.println("car.getCarPrice() = " + car.getCarPrice());
}
}
打印结果:
先获取xxxFactoryBean对象本身,再获取Car对象
package com.example;
import com.example.factory.MyFactoryBean01;
import com.example.pojo.Car;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import javax.annotation.Resource;
@SpringBootTest
class SpringSourceStudyApplicationTests {
@Autowired
private ApplicationContext applicationContext;
@Test
void test01() throws Exception {
// 调用 getBean() 参数前面添加& ,获取 MyFactoryBean01 对象本身
Object object = applicationContext.getBean("&myFactoryBean01");
System.out.println("该对象的类型 = " + object);
// 转为 MyFactoryBean01对象本身
MyFactoryBean01 myFactoryBean01 = (MyFactoryBean01) object;
// 获取Car对象
Car car = myFactoryBean01.getObject();
System.out.println("打印car对象信息 = " + car);
// 获取对象类型
Class<?> objectType = myFactoryBean01.getObjectType();
System.out.println("打印对象类型 = " + objectType);
// 获取Car对象是否是单例对象
boolean singleton = myFactoryBean01.isSingleton();
System.out.println("打印Car对象是否是单例对象 = " + singleton);
}
}
打印结果:
二、BeanFactory深入理解
- Spring本质是一个bean工厂(beanFactory)或者说bean容器。
- 在生产bean的过程中,需要解决bean之间的依赖问题,才引入了 `依赖注入(DI)`这种技术,依赖注入是BeanFactory生产bean时,为了解决bean之间的依赖的一种技术。
- 在没有beanfactory之前,我们都是通过new来实例化各种对象,现在各种对象bean的生产都是通过beanFactory来实例化,所以beanFactory在实例化bean的过程中(实例化bean的各个阶段),做一些额外的处理
- BeanFactory会在bean的生命周期的各个阶段中对bean进行各种管理,并且spring将这些阶段通过各种接口暴露给我们,让我们可以对bean进行各种处理,我们只要让bean实现对应的接口,那么spring就会在bean的生命周期调用我们实现的接口来处理该bean。
Bean在实例化之前,必须实在bean容器启动之后,所以就有了两个阶段:
- bean容器的启动阶段
- 容器中bean的实例化阶段
2.1 Bean容器的启动
1. 读取bean的各种定义
- 首先是读取bean的xml配置文件,然后解析xml文件中的各种bean的定义,将xml文件中的每一个<bean/>元素分别转换成 `BeanDefinition`对象,其中保存了从配置文件中读取到该bean的各种信息
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
@Nullable
private volatile Object beanClass;
@Nullable
private String scope = SCOPE_DEFAULT;
private boolean abstractFlag = false;
@Nullable
private Boolean lazyInit;
private int autowireMode = AUTOWIRE_NO;
private int dependencyCheck = DEPENDENCY_CHECK_NONE;
@Nullable
private String[] dependsOn;
private boolean autowireCandidate = true;
private boolean primary = false;
private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>();
@Nullable
private Supplier<?> instanceSupplier;
private boolean nonPublicAccessAllowed = true;
private boolean lenientConstructorResolution = true;
@Nullable
private String factoryBeanName;
@Nullable
private String factoryMethodName;
@Nullable
private ConstructorArgumentValues constructorArgumentValues;
@Nullable
private MutablePropertyValues propertyValues;
private MethodOverrides methodOverrides = new MethodOverrides();
@Nullable
private String initMethodName;
@Nullable
private String destroyMethodName;
}
- beanClass: 保存bean的class属性
- scope: 保存bean是否单例
- abstractFlag: 保存该bean是否抽象
- lazyInit: 保存是否延迟初始化
- autowireMode: 保存是否自动装配
- dependencyCheck: 保存是否依赖检查
- dependsOn: 保存该bean依赖哪些bean(这些bean必须提前初始化)
- constructorArgumentValues: 保存通过构造器注入的依赖
- propertyValues: 保存通过setter方法注入的依赖
- factoryBeanName和factoryMethodName: 用于FactoryBean,也就是工厂类型的bean
- initMethodName和destroyMethodName: 分别对应 bean的init-method 和 destroy-method 属性,比如:
读取配置文件之后,会得到很多 BeanDefinition对象。
2. 将Bean注册到BeanFactory
通过
BeanDefinitionRegistry
注册
public interface BeanDefinitionRegistry extends AliasRegistry {
// 注册beanDefinition
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException;
// 删除beanDefinition
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
// 获取beanDefinition
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
// 根据bean名称 是否在beanDefinition中存在
boolean containsBeanDefinition(String beanName);
// 获取beanDefinition中所有的名字
String[] getBeanDefinitionNames();
// 获取 beanDefinition的总数
int getBeanDefinitionCount();
// 根据bean名称判断是否被使用
boolean isBeanNameInUse(String beanName);
}
BeanFactory的实现类,需要实现BeanDefinitionRegistry 接口
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
/** bean定义对象的映射,以bean名称为键 */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
//---------------------------------------------------------------------
// BeanDefinitionRegistry接口的实现
//---------------------------------------------------------------------
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
if (beanDefinition instanceof AbstractBeanDefinition) {
// ..........
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// ........
}
}
- 我们看到 BeanDefinition 被注册到了 DefaultListableBeanFactory, 保存在它的一个 ConcurrentHashMap 中。
- 将 BeanDefinition注册到了 BeanFactory之后,在这里Spring为我们提供了一个扩展的接口,允许我们通过实现该接口 BeanFactoryPostProcessor 来插入我们自定的代码
@FunctionalInterface
public interface BeanFactoryPostProcessor {
/**
* 在标准初始化后修改应用程序上下文的内部bean工厂。所有的bean定义都将被加载,但是还没有bean被实例化。这允许重写或添加属性,甚至可以直接初始化bean。
* 形参: beanFactory—应用程序上下文使用的bean工厂
* 抛出: BeansException—在错误的情况
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
- 典型的例子就是: `PropertyResourceConfigurer`,我们一般在配置数据库的 dataSource时使用到的占位符的值(在xml中配置的${url}),就是它注入进去的:
public abstract class PropertyResourceConfigurer extends PropertiesLoaderSupport
implements BeanFactoryPostProcessor, PriorityOrdered {
/**
* 合并、转换和处理给定bean工厂的属性
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
try {
Properties mergedProps = mergeProperties();
// Convert the merged properties, if necessary.
convertProperties(mergedProps);
// Let the subclass process the properties.
processProperties(beanFactory, mergedProps);
}
catch (IOException ex) {
throw new BeanInitializationException("Could not load properties", ex);
}
}
/**
* 将给定的属性应用到给定的BeanFactory
* @param 应用程序上下文使用的beanFactory
* @param 要应用的属性
* @throws org.springframework.beans.BeansException in case of errors
*/
protected abstract void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props)
throws BeansException;
}
- processProperties(ConfigurableListableBeanFactory beanFactory, Properties props);在子类`PropertyPlaceholderConfigurer`中实现的功能就是将 {$jdbc_username}等等这些替换成实际值。
<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="url" value="${jdbc_url}" />
<property name="username" value="${jdbc_username}" />
<property name="password" value="${jdbc_password}" />
</bean>
/**
* 访问给定bean工厂中的每个bean定义,并尝试替换${…}属性占位符,其值来自给定属性
*/
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)
throws BeansException {
StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(props);
doProcessProperties(beanFactoryToProcess, valueResolver);
}
2.2 Bean的实例化阶段
- 实例化阶段:主要通过反射或者Cglib对bean进行实例化,在这个阶段Spring又给我们暴露了很多的扩展点
1. 各种Aware接口
- 比如: BeanFactoryAware、MessageSourceAware、ApplicationContextAware
- 对于实现了这些Aware接口的bean,在实例化bean时Spring会帮我们注入对应的: BeanFactory、MessageSource、ApplicationContext的实例:
public interface BeanFactoryAware extends Aware {
/**
* 向bean实例提供所属工厂的回调。
* 在普通bean属性填充之后,但在初始化回调(如InitializingBean.afterPropertiesSet()或自定义初始化方法之前调用)
* beanFactory: 拥有beanFactory(从不为空)。bean可以立即调用工厂上的方法
*/
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
public interface MessageSourceAware extends Aware {
/**
* 设置运行此对象的MessageSource。
* 在填充普通bean属性之后,但在初始化回调之前(如InitializingBean的afterPropertiesSet或自定义初始化方法)调用。
* 在ApplicationContextAware的setApplicationContext之前调用。
* messageSource: 该对象使用的消息源
*/
void setMessageSource(MessageSource messageSource);
}
public interface ApplicationContextAware extends Aware {
/**
* 设置该对象运行的ApplicationContext。
* 通常,此调用将用于初始化对象。
* 在填充普通bean属性之后,但在初始化回调(如org.springframework.beans.factory.InitializingBean.afterPropertiesSet()或自定义初始化方法之 * 前调用。
*/
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
2. BeanPostProcessor接口
- 实现了 BeanPostProcessor接口的bean,在实例化bean时Spring会帮我们调用接口中的方法:
public interface BeanPostProcessor {
/**
* 在任何bean初始化回调(如InitializingBean的afterPropertiesSet或自定义初始化方法)之前,
* 将这个BeanPostProcessor应用到给定的新bean实例。
* bean将已经被属性值填充。返回的bean实例可能是原始bean实例的包装器。 默认实现按原样返回给定的bean。
* @param bean 新的bean实例
* @param beanName bean的名称
* @return 要使用的bean实例,可以是原始的,也可以是封装后的;如果为null,则不会调用后续的BeanPostProcessors
* @throws BeansException
*/
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
/**
* 在任何bean初始化回调(如InitializingBean的afterPropertiesSet或自定义初始化方法)之后
* 将这个BeanPostProcessor应用到给定的新bean实例。
* bean将已经被属性值填充。
* 返回的bean实例可能是原始bean实例的包装器。
* 对于FactoryBean,这个回调将同时为FactoryBean实例和由FactoryBean创建的对象调用(从Spring 2.0开始)。
* 后处理程序可以通过相应的bean instanceof FactoryBean检查来决定是否应用于FactoryBean或已创建的对象,或者两者都应用。 该
* 回调也将在由InstantiationAwareBeanPostProcessor触发的短路后被调用。
* 方法,与所有其他BeanPostProcessor回调相反。 默认实现按原样返回给定的bean。
* @param bean 新的bean实例
* @param beanName bean的名称
* @return 要使用的bean实例,可以是原始的,也可以是封装后的;如果为null,则不会调用后续的BeanPostProcessors
* @throws BeansException
*/
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
- `postProcessBeforeInitialization`: 方法在 `InitializingBean`接口的 `afterPropertiesSet`方法之前执行
- `postProcessAfterInitialization`: 方法在 `InitializingBean`接口的 `afterPropertiesSet`方法之后执行
3. InitializingBean接口
- 实现了 InitializingBean 接口的bean,在实例化bean时Spring会帮我们调用接口中的方法:
public interface InitializingBean {
/**
* 在包含它的BeanFactory设置了所有bean属性并满足了BeanFactoryAware、ApplicationContextAware等之后,由它调用。
* 此方法允许bean实例在设置完所有bean属性后执行其总体配置验证和最终初始化
* @throws Exception
*/
void afterPropertiesSet() throws Exception;
}
4. DisposableBean接口
- 实现了 DisposableBean 接口的bean,在该bean死亡时Spring会帮我们调用接口中的方法:
public interface DisposableBean {
/**
* 在销毁bean时由包含bean的BeanFactory调用
* @throws Exception
*/
void destroy() throws Exception;
}
- `InitializingBean接口` 和 `DisposableBean`接口对应<bean />的 init-method 和 destory-method属性。
- <bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close" />
- 所以在Spring初始化 DataSource 这个bean之后会调用 DruidDataSource的init方法
// 基本就是初始化数据库连接池
public void init() throws SQLException {
// .........
}
- 在 DataSource 这个bean死亡时会调用 DruidDataSource的close方法:
// 关闭连接池中的连接
public void close() {
// .....
}
- 另外注解 `@PostConstruct` 和 `@PreDestroy` 也能达到 InitializingBean接口 和 DisposableBean接口的效果。
2.3 总结
- Spring容器接管了bean的实例化,不仅仅是通过依赖注入打到了松耦合的效果,同时给我们提供了各种的扩展接口,来在bean的生命周期的各个时期插入我们自己的代码:
- 0.BeanFactoryPostProcessor接口(在容器启动阶段)
- 1.各种的Aware接口
- 2.beanPostProcessor接口
- 3.initializingBean接口(@PostConstruct, init-method)
- 4.DisposableBean接口(@PreDestroy, destory-method)
三、Bean的生命周期
3.1 Bean生命周期的基本流程
1. 实例化 (通过反射创建对象)
2. 属性填充 (属性值非自动装配)
3. 初始化 (如:数据源复制、校验属性)
4. 销毁 (ioc容器销毁关闭、关闭数据源)
3.2 流程细节
1. 初始化方法和销毁方法
public class Book {
public void init(){
System.out.println("初始化方法");
}
public void destroy(){
System.out.println("销毁方法");
}
}
xml方式
<bean id="book" class="com.xc.enity.Book" init-method="init" destroy-method="destroy" />
@Bean的方式
@Bean(initMethod = "init",destroyMethod = "destroy")
public Book book(){
return new Book();
}
InitializingBean (初始化接口),DisposableBean(销毁接口) 实现其方法即可
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
public interface DisposableBean {
void destroy() throws Exception;
}
声明式注解 @PostConstruct (初始化) 、@PreDestory (销毁)
结论:
- 初始化销毁顺序: 声明式 -> 接口式 -> 自定义式
- 单例:容器关闭时销毁。
- 多例:容器关闭时不销毁。
2. BeanPostProcessor后置处理器
- 在所有初始化方法前后执行
- `spring所有bean初始化前后都会执行后置处理器`
- 可以定义多个后置处理器,一旦返回null,则跳过之后的处理器往下执行了
- 可以返回bean,也可以返回bean的包装对象 (aop动态代理)
/**
* @Author: codertl
* @Description:
* @Date: 2023/1/31
*/
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("前置处理器");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("后置处理器");
return bean;
}
}
3. xxAware接口
spring Aware 目的为了让bean获取spring容器中的服务。
- BeanNameAware: 获取容器中bean名称
- BeanFactoryAware: 获取BeanFactory容器
- ApplicationContextAware: 获取应用上下文
- `属性填充后,后置处理器前执行`
package com.example;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class BeanUtil implements ApplicationContextAware {
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public Object getBean(String beanName){
return context.getBean(beanName);
}
}
源码解析:
class ApplicationContextAwareProcessor implements BeanPostProcessor {}
3.3 总结
1. 实例化
2. 属性填充
3. 三种方式初始化
4. 处理Aware接口
5. BeanPostProcessor子接口的处理,如 `AutowiredAnnotationBeanPostProcessor`扫描`@autowired`注解,完成自动注入。
6. 处理各种后置处理器,在初始化方法后的后置方法中会根据情况包装代理类,即AOP
7. 销毁
四、Spring后置处理器
后置处理器有两种
1. bean的后置处理器: 这种处理器会对容器中的bean进行后处理,对bean进行增强。
2. 容器的后置处理器: 针对IOC容器的后处理,对容器功能增强。
4.1 bean后置处理器
- Bean的后置处理器是一种特殊的bean,主要负责容器中的其他bean执行后处理,如代理类的生成等,这种bean称为bean的后置处理器。
- 它会在bean创建成功后队bean进行增强处理。
- bean的后置处理器必须实现 `BeanPostProcessor`接口,同时实现两个方法:
- 1.`postProcessBeforeInitialization(Object bean, String beanName)`:前置处理,第一个参数是将进行处理的bean对象,第二个参数为该bean的id
- 2.`postProcessAfterInitialization(Object bean, String beanName)`: 后置处理
- bean后置处理器在容器中注册后,会自动启动,容器中的每个bean在创建时会自动执行后置处理器,Bean后置处理器两个方法执行回调的时机如下图:
- 在Bean注入依赖关系之后,bean初始化过程中,进行回调 `BeanPostProcessor`接口的 `postProcessBeforeInitialization` 和 `postProcessAfterInitialization`两个方法,对bean进行增强。
bean的初始化过程如下:
- 容器启动
- 收集 BeanDefinition (解析xml定义的bean信息)
- 实例化之前可以对bean做一个启动动作 (Spring提供了 InstantiationAwareBeanPostProcessor的postProcessBeforeInstantion()进行扩展)
- 根据加载的BeanDefinition信息通过反射实例化bean
- 实例化首先判断是否设置了 `super`对象,如果有则调用`super`的get得到父类对象,根据 BeanDefinition的信息确认bean实例化的方式通过工厂bean进行实例化或构造方法
- 实例化后赋值之前 MergeBeanDefinitionPostProcessor的 postProcessMergedBeanDefinition() 进行加工(扩展)
- 为对象属性赋值
- 赋值之后也有扩展点 InstantiationAwareBeanPostProcessor的 postProcessAfterInstantiation()
- 进行依赖注入 (循环依赖)
- 处理属性如: @Autowired、@Resource、@Value 等注解,通过上面的扩展点实现
- 完成属性赋值后,Spring执行回调
- 进行初始化,初始化之前提供了扩展点: BeanPostProcessor的postProcessorBeforeInitialization方法,可以对完成依赖注入的bean进行增强处理
- 初始化,查看是否实现初始化方法,调用初始化方法
- 初始化后spring提供了扩展点: BeanPostProcessor的postProcessorAfterInitialization方法进行扩展,可以bean进行最终的增强处理。
总结:Spring中的AOP就是基于初始化后实现的,初始化后返回的对象才是最终的对象
【注意】:如果使用BeanFactory
作为Spring容器,必须手动注册bean后置处理器才能生效。
4.2 容器的后置处理器
- 容器后置处理:负责容器本身的后置处理,必须实现 `BeanFactoryPostProcessor`接口,并实现方法 `postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)`对容器进行扩展。
标签:初始化,实例,Spring,理解,Bean,接口,bean,源码,public
From: https://www.cnblogs.com/codertl/p/17079375.html