zoukankan      html  css  js  c++  java
  • 自动装配组件@Resource和@Autowired的区别

      首先,梳理Spring中的byName与byType的基本概念;然后,介绍@Resource和@Autowired的使用方法,同时介绍了@Primary注解;最后,介绍二者的相同点和区别。

    byName与byType的概念

      首先,梳理一下基本概念,初步了解什么是byType,什么是byName。

    <bean id="userServiceImpl" class="cn.com.service.impl.UserServiceImpl" Autowire="byName">
    </bean>
    <bean id="userDao" class="cn.com.dao.impl.UserDaoImpl">
    </bean>
    

      比如说上面这段XML代码,autowire="byType"的意思是通过class="cn.com.dao.impl.UserDaoImpl"来查找UserDaoImpl下所有的对象,代码autowire="byName"意思是通过id="userDao"来查找Bean中的userDao对象。

      byName就是通过Bean的id或者name去自动装配,如果一个bean的name 和另外一个bean的 property 相同,就自动装配。byType就是按Bean的Class的类型去自动装配,如果一个bean的数据类型和另外一个bean的property属性的数据类型兼容,就自动装配。

    使用方法

       @Resource:按照名称(name)进行注入。该注解属于JDK中的注解,它在项目中使用频率比较高。

      @Autowired:按照类型自动装配。默认情况下要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,required属性的默认值为true。例如

    @Autowired(required=false) 
    @Qualifier("userService")
    private UserService userService;
    

       如果当Spring上下文中存在不止一个UserDao类型的组件时,就会抛出BeanCreationException异常,为了解决这个问题,@Autowired注解可以借助
    @Qualifier("组件名")注解来指明使用哪一个组件(实现类),实际上这是通过byName的方式实现。@Qualifier注解是java的规范,JRE标准

      @Primary:和@Qualifier 一样,可以使用@Primary注解让Spring进行自动装配的时候,默认使用哪个组件。使用场景经常是:对同一个接口,可能会有几种不同的实现类,而默认只会采取其中一种的情况下, @Primary 就会大显身手。

      例如,UserService有两个实现类UserServiceImpl和UserServiceImplDefault,而我们想默认使用后者,可以使用@Primary修饰UserServiceImplDefault类:

    
    @Service
    public class UserServiceImpl implements UserService {
        private static Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
    
        @Autowired
        private UserDao userDao;
        @Override
        public User getUserById(Long userId) {
            logger.info("--------*****-----------");
            return userDao.getUserById(userId);
        }
    }
    
    // ----------------- 我是分割线 -----------------
    
    @Primary
    @Component("defaultUserBean")
    public class UserServiceImplDefault implements UserService {
        private static Logger logger = LoggerFactory.getLogger(UserServiceImplDefault.class);
    
        @Autowired
        private UserDao userDao;
        @Override
        public User getUserById(Long userId) {
            logger.info("--------优先加载的组件-----------");
            return userDao.getUserById(userId);
        }
    }
    

       @Resource,默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上时,默认取属性名作为bean名称寻找依赖对象。需要注意的是,@Resource如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时, 它会回退到按类型装配。但是需要格外注意的是,一旦用name指定加载的组件名称,就只能按名称自动装配。

    @Resource (name= "userService" )
    private UserService userService;
    

      @Inject:和@Autowired注解一样也是按类型注入bean,但是没有required属性。使用此注解时需要导入javax.inject包。

      以上三个注解主要用于为类中属性自动注入bean,它们可以将(Spring IOC容器中的对象)装配到某些类的属性中。

    Spring注解实战

      例如,使用@Repository注册UserDao的组件到Spring容器:

    @Repository
    public interface UserDao {
        User getUserById(Long userId);
    }
    

      使用@Autowired把组件UserDao装配到UserServiceImpl实现类中:

    @Service
    public class UserServiceImpl implements UserService {
        private static Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
    
        @Autowired
        private UserDao userDao;
        @Override
        public User getUserById(Long userId) {
            logger.info("--------*****-----------");
            return userDao.getUserById(userId);
        }
    }
    

      这里,@Service将UserServiceImpl注册成组件托管给Spring容器。

    相同点与区别

      相同点:@Resource的作用相当于@Autowired,均可标注在字段或属性的setter方法上。

      不同点

      (1)提供方:@Autowired是由Spring提供,即由org.springframework.beans.factory.annotation.Autowired提供;@Resource是由JDK提供,即由javax.annotation.Resource提供,需要JDK6及以上。

      (2)注入方式:@Autowired只按照byType 注入;可以借助@Qualifier注解来指明使用哪一个实现类,@Resource默认按byName自动注入,也提供按照byType 注入。

      (3)属性:@Autowired 按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false。如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。

      (4)构造器:@Autowired 可以写在构造器上,用于注入bean,@Resource不可以。

      (5)@Resource注解不支持spring的@Primary注解优先注入,但是@Autowired支持。

    结束语

    @Autowied、@Resource或@Inject什么时候实现自动装配?启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IoC容器自动查找需要的组件,并装配给该对象的属性。

      推荐使用@Resource注解,使代码更加优雅,用它修饰字段后,就不用写setter方法了,并且这个注解是属于J2EE的,减少了与Spring的耦合。

      作为程序员,要有“刨根问底”的精神。知其然,更要知其所以然。这篇文章希望能抽丝剥茧,还原背后的原理。


      读后有收获,小礼物走一走,请作者喝咖啡。

    赞赏支持

  • 相关阅读:
    华为交换机配置和NTP服务器同步时间
    华为交换机常用查询命令
    Linux在线添加新磁盘
    华为交换机堆叠配置
    Linux-Centos安装nginx–解压版安装
    Linux修改为国内yum源
    pipenv的使用
    使用阿里云语音合成产品,从页面获取它的voice参数列表数据
    使用【Sonatype Nexus Repository Manager】搭建内部NPM源
    Vue3.0 项目中使用事件总线
  • 原文地址:https://www.cnblogs.com/east7/p/15316672.html
Copyright © 2011-2022 走看看