您当前的位置: 首页 >  spring

止步前行

暂无认证

  • 0浏览

    0关注

    247博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Spring中的BeanFactoryPostProcessor

止步前行 发布时间:2019-09-24 09:20:04 ,浏览量:0

一、引言

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

Spring中的后置处理器BeanPostProcessor

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

顾名思义: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()方法就是初始化方法。


这两个方法分别在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 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的创建。

关注
打赏
1657848381
查看更多评论
立即登录/注册

微信扫码登录

0.0369s