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;
    }
}
相关文章
相关标签/搜索