spring中后置处理器
作者:互联网
Spring后置处理器(BeanPostProcessor)(BeanFactoryPostProcessor) 原创
2020-12-23 11:25:52 2点赞 关注Spring的后置处理器,在应用Spring框架开发中非常重要,Spring底层的核心,就通过各种后置处理器去完成IOC容器的启动,AOP代理对象的创建。
Spring的后置处理器有两大类,BeanFactory
与Bean
。
BeanFactory
Bean 工厂方面的后置处理器
- BeanFactoryPostProcessor 获取IOC容器
- BeanDefinitionRegistryPostProcessor 向容器注册Bean
1:BeanFactoryPostProcessor
Spring是一个bean依赖注入容器,容器是BF,它的上级对象是applicationContxt,applicationContxt在容器功能上附加了一下新的功能。我们使用spring时,用的都是applicationConext的实现类。
我们在初始化这些applicationConext时,最终调用的都是org.springframework.context.support.AbstractApplicationContext#refresh方法用于容器的初始化。这个方法是一个模板方法,规定了容器实例化的步骤。其中BF初始化完成后,会调用BF的后置处理器对BF进行后置处理。而后置处理器的调用是在org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors这个方法中进行的。
可以拿到Spring的IOC容器。ConfigurableListableBeanFactory
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
invokeBeanFactoryPostProcessors方法内,调用后置处理器的步骤如下:
- 通过ac(applicationContext)的addBeanFactoryPostProcessor方法加入的BD后置处理器,按照加入顺序调用。
- ac中类型为bd后置处理器的,拥有PriorityOrdered接口的BD后置处理器。
- ac中类型为bd后置处理器的,拥有Ordered接口的BD后置处理器。
- ac中类型为bd后置处理器的,PriorityOrdered和Ordered接口都没实现的BeanDefinitionRegistryPostProcessor
- ac中类型为bf后置处理器的,拥有PriorityOrdered接口的BF后置处理器。
- ac中类型为bf后置处理器的,拥有Ordered接口的BF后置处理器。
- ac中类型为bf后置处理器的,PriorityOrdered和Ordered接口都没实现的BeanFactoryPostProcessor
在AnnotationConfigApplicationContext上下文中,会有一个关键的BD后置处理器:ConfigurationClassPostProcessor。它是用来扫描所有交给spring管理的注解类的。将其解析为BD实例放到AC中去。
2:BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistry Spring注册Bean的工具类,可以向容器手动注册Bean。
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
例如:
Bean
Bean 方面的后置处理器BeanPostProcessor,这个bean后置处理器在spring的底层用的非常的多
SmartInstantiationAwareBeanPostProcessor 设置Bean的类型,构造函数
InstantiationAwareBeanPostProcessor Bean实例化之前,属性赋值之前的处理器
MergedBeanDefinitionPostProcessor 再添加或修改Bean的定义信息
BeanPostProcessor Bean初始化之后的处理器,所有后置处理器的顶级接口。可以修改Bean实例的信息,甚至修改Bean的引用指向。
1:SmartInstantiationAwareBeanPostProcessor
设置Bean的类型,构造函数。基于Spring开发框架使用,平时开发不要使用。
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor { /** * 设置 Bean 的类型 */ default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException { return null; } /** * 设置创建 Bean用到的 构造函数 */ @Nullable default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException { return null; } /** * 循环引用从此处获取 Bean实例 */ default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException { return bean; } }
假如在创建一个UserService.class的Bean,如下我指定成EmployeeService.class,构造函数也是EmployeeService的无参构造函数,那么创建UserService Bean实例就会变成 EmployeeService的实例。
default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException { if (beanName.equals("userService")) { return EmployeeService.class; } return null; } /** * 设置创建 Bean用到的 构造函数 */ @Nullable default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException { if (beanName.equals("userService")) { try { return new Constructor[]{EmployeeService.class.getConstructor()}; } catch (Exception e) { } } return null; }
2:InstantiationAwareBeanPostProcessor
postProcessBeforeInstantiation:Bean实例化之前执行此方法,如果返回不为null,则替代当前准备实例化的Bean,Spring将不再自动实例化对象了。
postProcessAfterInstantiation:如果返回 true,执行 postProcessProperties方法。
postProcessProperties:设置实例化Bean需要的属性,调用 set 方法赋值,如果指定的属性名没有set方法,则报错。
/** * 在Spring实例化Bean之前调用,该方法如果返回结果不为空, * 这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。 * 如果该方法的返回值代替原本该生成的目标对象, * 后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走 * * @param beanClass Spring当前正在创建的Bean的类型 * @param beanName Spring当前正在创建的Bean的name * @return * @throws BeansException */ @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { return null; } /** * 在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。 * * 如果返回 true 调用 postProcessProperties设置属性值,然后 set 方法赋值 * @return * @throws BeansException */ public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { if (beanName.equals("userService")) { return true; } return false; } /** * 设置属性值 为 Bean的 set 方法赋值 * * 例如 添加了一个属性 password,会调用 bean的 setPassword方法,如果该方法没有,会报错 */ public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { if (beanName.equals("userService")) { ( (MutablePropertyValues) pvs).addPropertyValue(new PropertyValue("password", "123")); return pvs; } return null; }
3:MergedBeanDefinitionPostProcessor 再添加或修改Bean的定义信息
/** * @param beanDefinition 当前正在创建Bean的定义信息,可以用它再添加或修改一些定义信息 * beanDefinition.setLazyInit(true); 设置懒加载为 true */ void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName); /** * 如果修改了当前正在创建的Bean的 name 会执行 * @param beanName */ default void resetBeanDefinition(String beanName) { }
4:BeanPostProcessor
postProcessBeforeInitialization Bean初始化方法之前执行,可以返回一个对象,替代Spring当前的Bean实例。
postProcessAfterInitialization Bean初始化最后的一个处理方法,可以返回一个对象,替代Spring当前的Bean实例。AOP代理在此创建
@Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Nullable default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; }
Spring底层源码的总结:
看过Spring源码的,就会知道Spring的启动流程,只是提供了一个注册特定的组件(后置处理器),及实例化Bean的模板功能。其他功能:依赖注入,AOP切面,事务管理,异步执行…等等一系列的拓展功能,都是在后置处理器中执行。所以要学好Spring,就必选要搞懂它提供的后置处理器功能。
本文转自:https://blog.csdn.net/u014297148/article/details/80412991/
https://blog.csdn.net/liuqi199707/article/details/111540443
https://www.jianshu.com/p/6e32426a2497?u_atoken=8df0b569-f21e-41aa-b7a0-1794a0c45adc&u_asession=01NJYXBbd02B2joDTXDBO4WF6E6xmbjrq_3bTLJoyj6dJNOGIk8d7HtXNpyyzBQ60hX0KNBwm7Lovlpxjd_P_q4JsKWYrT3W_NKPr8w6oU7K88hgBKBWVVl9yMG4jTWLv5CvvWHyhA8I9G3hxoTho1LGBkFo3NEHBv0PZUm6pbxQU&u_asig=05PHkngCIBn4AI6DScvcchjiwnySJtQCKzFvojiVPdC7zb7vsBvJ_KO_D7vnh8ryrx8ozlX5syJtCNHMT6m_WE0G_S7BdbNlSN09n6J-zgnzzsfphKbJCNmjXA-h-UqR2NOoL2QZlpbxduKUE-3y2tnT70cDMDsjdDlLXoOFhWM_b9JS7q8ZD7Xtz2Ly-b0kmuyAKRFSVJkkdwVUnyHAIJzXS0idHrqpG2hDzDUwiEDG7-fKe0TvwVN4YTWQicPVaAChTz2MQxpCmDDGYlh3aZze3h9VXwMyh6PgyDIVSG1W88GDEzy7ZTJgWZe8pE5RdS7JPH1ToEoKDgsCNHHWCJPMVIGIuy3FU8GChSfyfUMWPcmeGRJXY26SLI-WXupu0AmWspDxyAEEo4kbsryBKb9Q&u_aref=U81RQlPfNZ%2FTEmX25m%2Bm79CqkHQ%3D
标签:return,后置,spring,beanName,Bean,处理器,Spring 来源: https://www.cnblogs.com/nizuimeiabc1/p/16629531.html