Spring中的BeanFactoryPostProcessor

一、引言

如果要想读懂Spring的源码,BeanPostProcessor和BeanFactoryPostProcessor这两种处理器机制应该要了解的。之前有过一篇文章,介绍了BeanPostProcessor后置处理器。

Spring中的后置处理器BeanPostProcessor

我们知道,Spring 提供了两种后处理Bean的扩展接口,分别为BeanPostProcessorBeanFactoryPostProcessor,这两者在使用上是有区别的。

顾名思义:BeanPostProcessor是用于对Bean做后置增强处理的;BeanFactoryPostProcessor是用于对BeanFactory做增强处理的。下面就来学习一下,它们的具体区别。

二、BeanPostProcessor

BeanPostProcessor:Bean级别的处理,针对某个具体的bean进行处理。

public interface BeanPostProcessor {

	Object postProcessBeforeInitialization(Object bean, String beanName);

	Object postProcessAfterInitialization(Object bean, String beanName);

}

BeanPostProcessor是个接口,上面是该接口仅有的两个方法,这两个方法执行的时机分别是Bean初始化前和Bean初始化后具体这个初始化方法指的是什么方法呢?就是我们在定义Bean时,定义了 init-method 所指定的方法,如下所示:其中init()方法就是初始化方法。

<bean id = "xxx" class = "xxx" init-method = "init()">

这两个方法分别在init()方法前后执行,需要注意一点,如果我们定义一个类实现了BeanPostProcessor,默认是会对整个Spring容器中所有的bean进行处理。

既然是默认全部处理,那么我们怎么确认我们需要处理的某个具体的Bean呢?

我们可以看到提供的两个方法中,有两个参数。类型分别为Object 和 String,第一个参数是每个Bean的实例,第二个参数是每个Bean的name或者id属性的值。所以我们可以根据第二个参数,来确定我们将要处理的具体的Bean。

这个类型的后置处理器处理是发生在Spring容器的实例化和依赖注入之后。

三、BeanFactoryPostProcessor

BeanFactoryPostProcessor:BeanFactory级别的处理,是针对整个Bean的工厂进行处理。

public interface BeanFactoryPostProcessor {

   void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory);
}

BeanFactoryPostProcessor也是个接口,上面是该接口的描述,此接口只提供了一个方法,方法参数为ConfigurableListableBeanFactory(其实是个扩展后的一个容器),下面看看这个类里面定义了哪些方法

public interface ConfigurableListableBeanFactory
				extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {

	void ignoreDependencyType(Class<?> type);

	void ignoreDependencyInterface(Class<?> ifc);

	void registerResolvableDependency(Class<?> dependencyType, Object autowiredValue);

	boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)

	BeanDefinition getBeanDefinition(String beanName) 
	
	Iterator<String> getBeanNamesIterator();

	void clearMetadataCache();

	void freezeConfiguration();

	boolean isConfigurationFrozen();

	void preInstantiateSingletons() throws BeansException;
}

其中有个方法名为getBeanDefinition的方法,我们可以根据此方法,找到我们定义Bean的BeanDefinition对象。然后我们可以对定义的属性进行修改,以下是BeanDefinition的定义。

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

	int ROLE_APPLICATION = 0;

	int ROLE_SUPPORT = 1;

	int ROLE_INFRASTRUCTURE = 2;

	void setParentName(String parentName);

	String getParentName();

	void setBeanClassName(String beanClassName);

	String getBeanClassName();
	
	void setScope(String scope);

	String getScope();

	void setLazyInit(boolean lazyInit);
	
	boolean isLazyInit();

	void setDependsOn(String... dependsOn);

	String[] getDependsOn();

	void setAutowireCandidate(boolean autowireCandidate);

	boolean isAutowireCandidate();
	
	void setPrimary(boolean primary);
	
	boolean isPrimary();

	void setFactoryBeanName(String factoryBeanName);
	
	String getFactoryBeanName();

	void setFactoryMethodName(String factoryMethodName);

	String getFactoryMethodName();

	ConstructorArgumentValues getConstructorArgumentValues();

	MutablePropertyValues getPropertyValues();

	boolean isSingleton();

	boolean isPrototype();

	boolean isAbstract();
	
	int getRole();

	String getDescription();

	String getResourceDescription();

	BeanDefinition getOriginatingBeanDefinition();

}

何为BeanDefinition?

从这个BeanDefinition定义中,我们可以看到,上面的很多属性和方法都很熟悉,例如类名、scope、属性、构造函数参数列表、依赖的Bean、是否是单例类、是否是懒加载等。这里其实就是将Bean的定义信息存储到这个BeanDefinition相应的属性中,后面对Bean的操作就直接对BeanDefinition进行。setBeanClassName对应Bean标签中的class属性,所以当我们拿到BeanDefinition对象时,我们可以手动修改Bean标签中所定义的属性值。例如拿到这个BeanDefinition后,可以根据里面的类名、构造函数、构造函数参数,使用反射进行对象创建。

BeanDefinition是一个接口,是一个抽象的定义,实际使用的是其实现类,如 ChildBeanDefinition、RootBeanDefinition、GenericBeanDefinition等。

具体这个BeanDefinition是个什么对象,当我们在xml中定义了Bean标签时,Spring会把这些Bean标签解析成一个Javabean,这个BeanDefinition就是Bean标签对应的Javabean。

所以当我们调用BeanFactoryPostProcess方法时,这时候Bean还没有实例化,此时Bean刚被解析成BeanDefinition对象。(☆☆☆☆☆)

Spring容器初始化Bean大致过程:

定义Bean标签---->将Bean标签解析成BeanDefinition ----> 调用构造方法实例化(IOC)(创建对象) ---->属性值依赖注入(DI)(属性赋值)

所以BeanFactoryPostProcessor中的BeanFactoryPostProcess方法的执行是发生在第二步之后,第三步之前。

而BeanPostProcessor作用于第三步之后。

四、小结

以上两种都为Spring提供的后处理Bean的接口BeanPostProcessor和BeanFactoryPostProcessor,两者执行的时机不一样。前者在Bean实例化和属性赋值之后执行,后者是Bean实例化之前执行。从功能上来看,BeanFactoryPostProcessor对Bean的处理功能更加强大。因为它可以改变Bean的创建。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

止步前行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值