1. 概述
Spring
有很强的扩展性,主要体现在它为外界提供了许多钩子方法, 比如Aware
、BeanPostProcessor
、InitializingBean
、init-method
等都是 Spring
提供的扩展点
2. Aware
接口
spring源码:Aware接口
若 Spring
检测到 bean
实现了 Aware
接口,则会为其注入相应的依赖。所以通过让bean
实现 Aware
接口,则能在 bean
中获得相应的 Spring
容器资源。
Spring
中提供的 Aware
接口有:
BeanNameAware
:注入当前 bean
对应 beanName
;
BeanClassLoaderAware
:注入加载当前 bean
的 ClassLoader
;
BeanFactoryAware
:注入 当前BeanFactory
容器 的引用
ApplicationContextAware
如我们想得到当前的BeanFactory
,我们可以让我们的实现类继承BeanFactoryAware
接口,然后通过接口注入的方式得到当前容器中的BeanFactory
:
public class Fruit implements BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
}
aware
接口的各种处理是在属性设置完成之后、bean
初始化之前完成的
3. InitializingBean
和 DisposableBean
接口
InitializingBean
是 Spring
为 bean
初始化提供的扩展点,可以添加自定义的初始化方法或者做一些资源初始化操作,当BeanFactory
设置完所有的Bean
属性之后才会调用afterPropertiesSet
方法
InitializingBean
接口 的定义如下
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
DisposableBean
接口只有一个方法destroy
,作用是:当一个单例Bean
实现DisposableBean
,destroy
可以添加自定义的一些销毁方法或者资源释放操作
4. init-method
指定 init-method
方法,指定初始化方法:
package com.minifull.pojo;
import org.springframework.beans.factory.BeanNameAware;
public class User implements BeanNameAware {
private String name;
private int age;
public User() {
System.out.println("Bean:初始化");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("设置属性");
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//调用BeanNameAware的setBeanName()
//传递Bean的ID
public void setBeanName(String name) {
System.out.println("调用BeanNameAware的setBeanName()..." );
}
//Bean的初始化方法
public void initUser() {
System.out.println("Bean:initmethod");
}
//Bean的销毁方法
public void destroyUser() {
System.out.println("Bean:销毁");
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class MyBeanPostProcessor implements BeanPostProcessor {
//对初始化之后的Bean进行处理
//参数:bean:即将初始化的bean
//参数:beanname:bean的名称
//返回值:返回给用户的那个bean,可以修改bean也可以返回一个新的bean
public Object postProcessAfterInitialization(Object bean, String beanname) throws BeansException {
User user = null;
System.out.println("后置处理器,将Bean的成员变量的值修改了");
if("name".equals(beanname) || bean instanceof User) {
user = (User) bean;
user.setName("Jack");
}
return user;
}
//对初始化之前的Bean进行处理
//参数:bean:即将初始化的bean
//参数:beanname:bean的名称
//返回值:返回给用户的那个bean,可以修改bean也可以返回一个新的bean
public Object postProcessBeforeInitialization(Object bean, String beanname) throws BeansException {
System.out.println("前置处理器,此时我的名字"+bean);
return bean;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="user" class="com.minifull.pojo.User" init-method="initUser" destroy-method="destroyUser">
<property name="age" value="1"></property>
<property name="name" value="minifull"></property>
</bean>
<!-- 配置bean的后置处理器,不需要id,IoC容器自动识别是一个BeanPostProcessor -->
<bean class="com.minifull.pojo.MyBeanPostProcessor"></bean>
</beans>
public class FilAppTest {
@Test
public void test1(){
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:applicationContext.xml");
Object user = applicationContext.getBean("user");
System.out.println(user);
((AbstractApplicationContext) applicationContext).close();
}
@Test
public void dailyCircleTest(){
}
}
5. 后置处理器
Spring的BeanFactoryPostProcessor和BeanPostProcessor
Spring
框架中提供了各种PostProssor
后置处理器,他们本身也是一种注册到容器中的Bean
,其里面定义的方法会在特定的时机被容器调用,实现不改变容器或者Bean
核心逻辑的情况下对Bean
进行扩展,从而达到对Bean
的包装,影响Bean
的行为,修改Bean
的内容等目的;
Spring
提供的后置处理器大致分为容器级别的后置处理器和Bean
级别的后置处理器
BeanDefinitionRegistryPostProcessor
BeanFactoryPostProcessor
BeanPostProcessor
① BeanFactoryPostProcessor
接口
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
Spring
允许BeanFactoryPostProcessor
在容器实例化任何其它bean
之前读取配置元数据,并可以根据需要进行修改,例如可以把bean
的scope
从singleton
改为prototype
,也可以把property
的值给修改掉;它是在spring
容器加载了bean
的定义文件之后,在bean
实例化之前执行的;
Spring
允许可以同时配置多个BeanFactoryPostProcessor
,并通过设置order
属性来控制各个BeanFactoryPostProcessor
的执行次序,看下面的例子
User
public class User implements BeanNameAware {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
UserBeanFactoryPostProcessor
public class UserBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
/**
*
* @param beanFactory 从工厂中可以获取到相关bean的定义信息
* @throws BeansException
*/
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("调用UserBeanFactoryPostProcessor的postProcessBeanFactory");
BeanDefinition user = beanFactory.getBeanDefinition("user");
String scope = user.getScope();
System.out.println("User的是:"+scope);
if(scope.equals(BeanDefinition.SCOPE_SINGLETON)){
user.setScope(BeanDefinition.SCOPE_PROTOTYPE);
System.out.println("更改为"+user.getScope());
}
//value
MutablePropertyValues propertyValues = user.getPropertyValues();
System.out.println("user.age:"+propertyValues.get("age"));
System.out.println("将年龄更改为22");
propertyValues.addPropertyValue("age",22);
System.out.println("UserBeanFactoryPostProcessor的postProcessBeanFactory调用结束");
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="user" class="com.minifull.pojo.User" scope="singleton">
<property name="name" value="minifull"></property>
<property name="age" value="21"></property>
</bean>
<bean id="userBeanFactoryPostProcessor" class="com.minifull.postprocessorpag.UserBeanFactoryPostProcessor"></bean>
</beans>
@Test
public void beanFactoryPostProcessortest(){
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:applicationContext.xml");
User user = (User)applicationContext.getBean("user");
System.out.println(user);
}
结果如下
② BeanPostProcessor
接口
BeanPostProcessor
,可以在spring
容器实例化bean
之后,在执行bean
的初始化方法前后,添加一些自己的处理逻辑。这里说的初始化方法,指的是下面两种:
① bean
实现了InitializingBean
接口,对应的方法为afterPropertiesSet
② 在bean
定义的时候,通过init-method
设置的方法
public interface BeanPostProcessor {
// 初始化前置处理
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
// 初始化后置处理
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
这一点在AbstractAutowireCapableBeanFactory
创建bean
的源码中有所表现
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 1. 创建实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
...
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 2. 装载属性
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 3. 初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
...
}
在上面第 3 步 initializeBean(...)
方法中会调用 BeanPostProcessor
中的方法,如下:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
...
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 1. 执行每一个 BeanPostProcessor 的 postProcessBeforeInitialization 方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 调用 bean 配置中的 init-method="xxx"
invokeInitMethods(beanName, wrappedBean, mbd);
}
...
if (mbd == null || !mbd.isSynthetic()) {
// 我们关注的重点是这里!!!
// 2. 执行每一个 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
BeanPostProcessor
的常用场景有:
- 对于标记接口的实现类,进行自定义处理
- 为当前对象提供代理实现。例如
Spring AOP
功能,生成对象的代理类,然后返回
使用如下:
/**
* bean的后置处理器
* 分别在bean的初始化前后对bean对象提供自己的实例化逻辑
* postProcessAfterInitialization:初始化之后对bean进行增强处理
* postProcessBeforeInitialization:初始化之前对bean进行增强处理
*
*/
public class MyBeanPostProcessor implements BeanPostProcessor {
//对初始化之后的Bean进行处理
//参数:bean:即将初始化的bean
//参数:beanname:bean的名称
//返回值:返回给用户的那个bean,可以修改bean也可以返回一个新的bean
public Object postProcessAfterInitialization(Object bean, String beanname) throws BeansException {
User user = null;
System.out.println("对初始化之后的Bean进行处理,将Bean的成员变量的值修改了");
if("name".equals(beanname) || bean instanceof User) {
user = (User) bean;
user.setName("Jack");
}
return user;
}
//对初始化之前的Bean进行处理
//参数:bean:即将初始化的bean
//参数:beanname:bean的名称
//返回值:返回给用户的那个bean,可以修改bean也可以返回一个新的bean
public Object postProcessBeforeInitialization(Object bean, String beanname) throws BeansException {
System.out.println("对初始化之前的Bean进行处理,此时我的名字"+bean);
return bean;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="user" class="com.minifull.pojo.User">
<property name="age" value="1"></property>
<property name="name" value="minifull"></property>
</bean>
<!-- 配置bean的后置处理器,不需要id,IoC容器自动识别是一个BeanPostProcessor -->
<bean class="com.minifull.pojo.MyBeanPostProcessor"></bean>
</beans>
BeanPostProcessor
的家庭成员
InstantationAwareBeanPostProcessor
接口
这个接口的作用是在Bean的实例化的过程中给Bean
加上额外的逻辑,注意这里说的是实例化的过程,是在初始化和赋上属性之前;
InstantationAwareBeanPostProcessor
接口中定义了三个方法
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
//在对象实例化之前调用,直接返回一个对象(如代理对象)来代替通过内置的实例化流程创建对象
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
//在对象实例化完成后,执行populateBean之前,判断是否继续进行对属性赋值的流程
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
//在Spring处理完默认的成员属性,应用到指定的bean之前进回调,可以用来检查和修改属性
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
}
也就是说bean
的生命周期实际上是这样的
当调用getBean()
1.调用InstantationAwareBeanPostProcessor的postProcessBeforeInstantation方法
2.实例化bean
3.调用InstantationAwareBeanPostProcessor的postProcessAfterInstantation方法(如果有返回值 则跳转到11)
4.尝试设置属性:调用InstantationAwareBeanPostProcessor的postProcessPropertyValues-
5.设置属性
6.调用beanNameAware的setBeanName方法
7.调用BeanFactoryAware的setBeanFacotroy方法
8.之后初始化: 先调用BeanPostProcessor的postProcessBeforeInitializing()
9.初始化,调用<init-method>指定的方法,或者是@PostConstruct方法
10.调用InitializingBean的afterPropertySet()方法
11.调用BeanPostProcessor的postProcessAfterInitializaiton()方法
如果bean是prototype型的,则直接返回这个bean
如果是singleton型的,则加入到Spring的缓存池中,下次调用直接从缓存池中取得
这些在AbstractAutowireCapableBeanFactory
的源码中都有体现
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
//....省略无关代码
try {
//如果Bean配置了InstantiationAwareBeanPostProcessor接口,也就是初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
}
try {
//创建Bean的入口
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
}
catch (Throwable ex) {
}
}
可以看到在doCreateBean
方法前会调用resolveBeforeInstantiation
,我们所配置的InstantiationAwareBeanPostProcessor
后置处理器就是在这里执行的,并且在执行InstantiationAwareBeanPostProcessor
后置处理器后就会把生成的对象返回也就不再执行doCreateBean
方法,即Spring的初始化bean
的流程
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
//如果beforeInstantiationResolved还没有设置或者是false(说明还没有需要在实例化前执行的操作)
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
//mbd.isSynthetic()默认是true,
// 如果注册了InstantiationAwareBeanPostProcessors类型的BeanPostProcessor,
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//PostProcessorsBeforeInstantiation
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
//PostProcessorsAfterInitialization
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
③ BeanDefinitionRegistryPostProcessor
接口
BeanDefinitionRegistryPostProcessor
继承了BeanFactoryPostProcessor
接口
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
//该方法用来注册更多的bean到spring容器中
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
//继承自BeanFactoryPostProcessor的方法 主要用来对bean定义做一些改变
//void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
可以看到除了继承自BeanFactoryPostProcessor
的postProcessBeanFactory
方法以外,还有postProcessBeanDefinitionRegistry
方法,他的参数BeanDefinitionRegistry
提供了丰富的方法来操作bean
定义,判断、注册、反注册,使用它来注册更多的bean
到spring
容器中
@Configuration
public class CustomizedBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
Class<User> clazz = User.class;
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
GenericBeanDefinition beanDefinition = (GenericBeanDefinition) builder.getRawBeanDefinition();
registry.registerBeanDefinition("user",beanDefinition);
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
在对 BeanDefinitionRegistryPostProcessor
里面的方法进行执行的时候,Spring
使用了责任链模式//TODO
6. FactoryBean
接口
Spring
中有两种类型的Bean
,一种是普通Bean
,另一种是工厂Bean
,即FactoryBean
,这两种Bean
都被容器管理,但工厂Bean
跟普通Bean
不同,其返回的对象不是指定类的一个实例,其返回的是该FactoryBean
的getObject
方法所返回的对象;
在Spring
框架内部,有很多地方有FactoryBean
的实现类,它们在很多应用如(Spring
的AOP
,ORM
,事务管理)及与其它第三框架(hibernate
,mybatis
,jpa
…)集成时都有体现
public interface FactoryBean<T> {
//返回由FactoryBean创建的bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中
T getObject() throws Exception;
//返回FactoryBean创建的bean类型
Class<?> getObjectType();
//返回由FactoryBean创建的bean实例的作用域是singleton还是prototype
boolean isSingleton();
}
通过Spring
容器的getBean()
方法返回的不是FactoryBean
本身,而是FactoryBean.getObject()
方法所返回的对象,相当于 FactoryBean.getObject()
代理了getBean()
方法。如果希望获取FactoryBean
的实例,则需要在使用getBean(beanName)
方法时在beanName
前显示的加上 "&"
前缀