spring容器中Bean的加载包含一系列的过程,bean的启动过程主要是org.springframework.context.support.AbstractApplicationContext.refresh() 方法。主要阶段包含:
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
其中这个:
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
意思就是调用注册PostProcessor。进入invokeBeanFactoryPostProcessors函数。最后调用栈会执行到:
void org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors)
这里将会处理这些Processor。
实现ApplicationContext接口之下的具体类的容器都是在容器初始化的时候实例化了对象,初始化的时候我们如果要对实例进行干预可以实现org.springframework.beans.factory.config.BeanFactoryPostProcessor。我们可以利用这个接口做一些事情,例如我们可以在数据库里配置密码为密文,然后使用程序需要使用的对象动态的解密数据,这样达到安全性保证。
我们定义:
class User {
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
配置初始化参数:
<bean id="user" class="micro.test.spring.User">
<property name="password" value="123456"></property>
</bean>
测试:
User user = context.getBean("user",User.class);
System.out.println(user.getPassword());
打印 : 123456
如果我们干预一下User的实例化:
class MyPostBeanProcessor extends SpringBase implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 修改user
User user = (User) beanFactory.getBean("user",User.class);
// 模拟加密算法
// 真实密码为原来的密码数字对应的+1
user.setPassword(decode(user.getPassword()));
}
private String decode(String password) {
StringBuffer sb = new StringBuffer();
for (char c : password.toCharArray()) {
sb.append((int) c - 47);
}
return sb.toString();
}
}
测试为:
234567
完成了实例化动态修改配置的效果