在使用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; } }