Spring @Resource 忽略 required

本文探讨了Spring框架中@Autowired和@Resource注解的使用差异,特别是关于是否允许注入对象为null的特性。通过重写CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor,实现了@Resource和@Autowired全局允许注入null对象的功能,适用于单元测试等场景。

在使用spring 自动注入对象通常会用到@Autowired (spring 自定义注解)、@Resource (JSR-250规范定义的注解) 两个注解,在使用中@Autowired 支持 required = false 的设置可以允许注入对象为null,而@Resource 不支持该特性 (王侯将相宁有种乎?), 手动扩展spring使其支持null对象注入。


  • 探究源码
// @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加了个全局开关。

  • 实现@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;
    }
}

转载于:https://my.oschina.net/u/1793436/blog/2396067

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值