如何玩转Spring的BeanPostProcessor.

在Spring初始化bean的步骤中,有一步执行前缀/后置初始化的处理(BeanPostProcessor)的逻辑。这为我们提供了扩展Bean的功能,IOC的强大功能就在于此。

在讲解之前,这里要说一下InitializingBean和BeanPostProcessor的区别,必免混淆。两个接口都可以执行bean初始化前置处理的功能。区别在于InitializingBean是目标Bean主动实现的接口(常用业务逻辑可以写在里面),而BeanPostProcessor是由BeanFatotry在Bean初始化时把Bean作为参数传入BeanPostProcessor执行的(具体BeanPostProcessor是被存储在AbstractBeanFactory中的一个List中)。暂且说成被动执行。

BeanPostProcessor的实现类主要是Spring自带的一些辅助类,比如注解扫描类(CommonAnnotationBeanPostProcessor,xml中配置为<context:component-scan> ),配置以后会自动扫描标记了@Controller,@Service等注解的类,提供给其它类进行注入。

下面介绍另一个配合hibernate使用BeanPostProcessor的另一个场景。我们有这样一种场景,如何让容器在启动的时候加载各模块之间配置的mapping文件呢。

首先看一下常规的做法,在sessionFactory中显示的配置。

<bean id="routeSessionFactory" name="routeSessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="routeDataSourceLocal" />
<property name="mappingResources">
<list>
<value>com/sf/module/routeshare/META-INF/config/mapping.xml</value>
.....//添加其它mapping.xml文件
</list>
</property>

此种做法不好的地方在于多个模块同时开发时,需要修改同一个文件,不利于管理。

其实BeanPostProcessor提供了一种便捷的方式,在容器启动时,先收集好mapping.xml文件的位置,在实例化LocalSessionFactoryBean时把mapping数组注入到mappingResources属性中。
具体步骤如下:
1.web.xml中配置容器启动后的监听器。

<listener>
<listener-class>com.xxx.framework.server.core.deploy.FrameworkListener</listener-class>
</listener>


2.加载所有mapping文件的路径。

//始始化容器时读取mapping文件路径。
private Application initApplication()
{
//加载指定路径下各模块的mapping.xml文件。
List mappingConfigs = initConfigs("/META-INF/config/mapping.xml",
moduleNames);
...}

//使用spring工具类进行解析
private List initConfigs(String configName, List configs)
{
try
{
Resource resources[] = new PathMatchingResourcePatternResolver().getResources((new StringBuilder("classpath*:com/xxx/**")).append(configName).toString());
for(int i = 0; i < resources.length; i++)
{
Resource resource = resources[i];
try
{
String file = resource.getURL().getPath();
String config = file.substring(file.lastIndexOf("com/sf/"));
if(!configs.contains(config))
{
configs.add(config);
}
.....

}


3.编写BeanPostProcessor。

public class MappingAutowiring
implements BeanPostProcessor
{

public MappingAutowiring()
{
}

public String[] getMappingResources()
{
return mappingResources;
}

//此方法通过MappingFactoryBean进行注入,里面会获取到之前Application的mapping的路径
public void setMappingResources(String mappingResources[])
{
this.mappingResources = mappingResources;
}

public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException
{
if(bean instanceof LocalSessionFactoryBean)
{
log.debug((new StringBuilder("============ MappingAutowiring: ")).append(mappingResources).toString());
((LocalSessionFactoryBean)bean).setMappingResources(mappingResources);
}
return bean;
}


<!--配置MappingAutowiring -->
<bean id="mappingAutowiring" class="com.xxx.framework.server.core.deploy.MappingAutowiring">
<property name="mappingResources" ref="mappingResources" />
</bean>
<bean id="mappingResources" class="com.xxx.framework.server.core.deploy.MappingFactoryBean" />



public class MappingFactoryBean
implements FactoryBean
{
public MappingFactoryBean(){}

public Object getObject()
throws Exception
{
List configs = ApplicationContext.getContext().getApplication().getMappingConfigs();

return ((Object) (configs.toArray(new String[configs.size()])));
}

....
}

从上述代码看出,通过BeanPostProcessor的postProcessBeforeInitialization方法,可以给LocalSessionFactoryBean注入mapping文件的路径
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值