因为项目需求,要实现自定义注解然后通过spring扫描注解并放入缓存,我想到了BeanDefinitionRegistryPostProcessor接口,通过实现 BeanDefinitionRegistryPostProcessor接口postProcessBeanFactory方法实现,因为这个方法的入参postProcessBeanFactory可以得到所有已注入spring的bean,然后获得自定义注解修饰的bean。到这一切正常,但是我发现在操作的时候属性配置${name}没有被加载到bean当中,这是什么原因?
不得不说下spring配置文件的加载顺序,当使用spring配置文件时,首先加载bean然后加载import进入spring的bean,当然可以再web.xml中添加配置文件,这时按顺序加载。
我的配置文件读取不到,不得不说下BeanDefinitionRegistryPostProcessor接口,他是在bean定义之后,实例化之前执行的接口,Spring 框架会根据配置,过滤出 BeanDefinitionRegistryPostProcessor 类型的 Bean 定义,并通过 Spring 框架生成其对应的 Bean 对象(如 ConfigurationClassPostProcessor 实例)。结合 Spring 上下文源码可知这个对象是一个 processor 类型工具类,Spring 容器会在实例化开发人员所定义的 Bean 前先调用该 processor 的 postProcessBeanDefinitionRegistry(...) 方法。这时他也影响了PropertyPlaceholderConfigurer所加载的properties,在其中操作时占用了properties,这时其他需要properties的bean没有完成初始化,也就是properties没有被写入到bean当中,所以就导致${name}没有被执行。
这种解决办法就在于在postProcessBeanDefinitionRegistry方法不延缓执行时间而是另起线程对configurableListableBeanFactory进行处理。这样不影响bean的实例化。
public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) {
Set<String> beanNames = new LinkedHashSet<String>(getBeanDefinitionCount());
beanNames.addAll(Arrays.asList(getBeanDefinitionNames()));
beanNames.addAll(Arrays.asList(getSingletonNames()));
Map<String, Object> results = new LinkedHashMap<String, Object>();
for (String beanName : beanNames) {
if (findAnnotationOnBean(beanName, annotationType) != null) {
results.put(beanName, getBean(beanName));
}
}
return results;
}//源码中对注解bean的获取。这里get方法并没有对configurableListableBeanFactory进行修改。所以不会是改变了它导致properties的处理失败。
因为postProcessBeanFactory是void方法,所以一定是并发执行,只是执行顺序会快一些,这是如果延缓了处理时间,导致后面bean的实例化${name}出问题也就情有可原了。
。。PropertyPlaceholderConfigurer其实也实现了BeanDefinitionRegistryPostProcessor接口。但是执行顺序是在前面的,但是它这是并没有初始化。
但是这个延缓,我总感觉过于牵强!但是确实没有对它进行操作。
看到的提提意见,欢迎指出错误~