Spring @Resource 忽略 required

在使用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;
	}		
}
  • 擴展BeanPostProcessor
/**
 * 直接繼承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的全局容許爲null的擴展
/**
 * @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;
    }
}
相關文章
相關標籤/搜索