在使用spring 自动注入对象一般会用到@Autowired (spring 自定义注解)、@Resource (JSR-250规范定义的注解) 两个注解,在使用中@Autowired 支持 required = false 的设置能够容许注入对象为null,而@Resource 不支持该特性 (王侯将相宁有种乎?), 手动扩展spring使其支持null对象注入。java
// @Resource注解使用的是CommonAnnotationBeanPostProcessor处理器 public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable { /** * 经过注入对象的名称从BeanFactory提取bean 对象 */ protected Object autowireResource(BeanFactory factory, LookupElement element, String requestingBeanName) throws BeansException { Object resource; Set<String> autowiredBeanNames; String name = element.name; if (this.fallbackToDefaultTypeMatch && element.isDefaultName && factory instanceof AutowireCapableBeanFactory && !factory.containsBean(name)) { autowiredBeanNames = new LinkedHashSet<String>(); resource = ((AutowireCapableBeanFactory) factory).resolveDependency( element.getDependencyDescriptor(), requestingBeanName, autowiredBeanNames, null); } else { resource = factory.getBean(name, element.lookupType); autowiredBeanNames = Collections.singleton(name); } if (factory instanceof ConfigurableBeanFactory) { ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory; for (String autowiredBeanName : autowiredBeanNames) { if (beanFactory.containsBean(autowiredBeanName)) { beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName); } } } return resource; } }
/** * 直接继承CommonAnnotationBeanPostProcessor * 做为BeanPostProcessor组件加载 */ @Component public class AutoResourceNull extends CommonAnnotationBeanPostProcessor { /** * 重写autowireResource方法。 * 在获取注入对象是若是为null捕获异常从而返回null对象,不影响spring 容器加载 */ @Override protected Object autowireResource(BeanFactory factory, LookupElement element, String requestingBeanName) throws BeansException { Object obj = null; try { obj = super.autowireResource(factory, element, requestingBeanName); } catch (Exception e) { System.err.println(e.getMessage()); } return obj; } }
经过重写CommonAnnotationBeanPostProcessor在对象注入前,重写该类中autowireResource 方法,在BeanFactory中找不到该对象是默认返回null对象给到引用方,从而不影响这个spring容器的加载,多数状况下用于单元测试阶段 (由于不想由于不相干的bean对象找不到从而影响整个spring容器的加载)。有一个缺点就是不能像@Autowired那样细粒度控制到具体某个对象容许为null,这里至关于给@Resource加了个全局开关。spring
/** * @Autowired 和 @Inject 使用的是 AutowiredAnnotationBeanPostProcessor 处理器 */ @Component public class AppTest extends AutowiredAnnotationBeanPostProcessor { /** * 同理,在获取bean对象时捕获异常返回null对象 */ @Override public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException { try { pvs = super.postProcessPropertyValues(pvs, pds, bean, beanName); } catch (BeanCreationException e) { System.err.println(e.getMessage()); } return pvs; } }