zoukankan      html  css  js  c++  java
  • Spring框架中@Autowired和@Resource的区别


    Spring框架中@Autowired和@Resource的区别


    在下载spring源码的漫长过程中....整理一下@Autowired 和 @Resource两个注解的区别和理解


    1、注入原理

    注入就是为某个对象的外部资源赋值(利用反射机制为类的属性赋值的操作),注入某个对象所需要的外部资源(包括对象、资源、常量数据等)

    • @Autowired是Spring的注解,Autowired默认先按 byType,如果发现找到多个 bean,则,又按照 byName方式比对,如果还有多个,则报出异常;

    • @Resource 是JDK1.6支持的注解默认按照名称( ByName)进行装配, 如果没有指定 name属性,当注解写在字段上时,默认取字段名,按照名称查找,如果注解写在 setter方法上默认取属性名进行装配。当找不到与名称匹配的 bean时才按照类型进行装配。

    但是需要注意的是,如果 name属性一旦指定,就只会按照名称进行装配。

    2、简单实例

    UserService 接口

    @Service
    public interface UserService {
    	public User findByUsername(String username);
    }
    

    UserServiceImpl 实现类

    @Service
    public class UserServiceImpl implements UserService{
    
    	@Override
    	public User findByUsername(String username) {
    		return username;
    	}
    }
    

    Controller中具体调用

    @Controller
    public class UserCenterController {
    	@Autowired 
        UserService userService;
        
        userService.findByUsername("pianpianpianpian");
    
    }
    	
    

    3、获取实例的具体过程

    在Controller类中获取实例 userService时,若使用的是@Autowired,则程序在spring容器中查找相应的类型(UserService类型)的bean,这里刚好有且只有一个对应的bean(UserServiceImpl),则就把UserServiceImpl 自动装配到Controller类的实例(userService)中去了。值得一提的是这里的userService其实就是**UserServiceImpl **这个实现类。

    同理,使用@Resource时候

    先在容器中查找名为 userService的bean,在这个实例中是肯定找不到的,因为容器中的bean的名字应该是UserServiceImpl 实例中的@Service没有指定bean的value属性,所以注入的bean的名字就是类名,反之如果指定了就是指定的名字)。前面说到按照名字查找没有找到,然后再通过类型查找userService类型的bean,可以找到唯一的一个userService类型的bean(即实现类**UserServiceImpl **)


    ps: 小结,个人理解的是 这里的接口是不会被注入bean的,只是用来接收数据和做规范的

    通过查阅资料,发现这两个注解的效率是差不多的,不过@Resource可以应对一个接口对应多个实现类的情况,而@Autowired需要结合注解@Qualifier来使用。所以综合来说@Resource更好一点。

    4、拓展

    Q1、如果遇到一个接口对应多个实现类的情况:

    如: UserServiceImpl 和 UserServiceImplSec两个相同类型的类

    @Service
    public class UserServiceImpl implements UserService{
    
    	@Override
    	public User findByUsername(String username) {
    		return username;
    	}
    }
    
    @Service
    public class UserServiceImplSec implements UserService{
    
    	@Override
    	public User findByUsername(String username) {
    		return username;
    	}
    }
    

    可以通过以下两种方法确定具体要实例化的类:

    1、使用 @Autowired + @Qualifier 或者 @Resource

    	@Autowired
        @Qualifier("UserServiceImpl")
        private UserServiceImpl userServiceImpl;
    ---------------------------------------------------
        @Resource(name = "UserServiceImpl")
        private UserServiceImpl userServiceImpl;  
    
    

    2、在实现类上添加 @Primary 注解来指定默认加载类

    @Service
    @Primary
    public class UserServiceImpl implements UserService{
    
    	@Override
    	public User findByUsername(String username) {
    		return username;
    	}
    }
    

    Q2、Controller中明明可以直接实例化实现类UserServiceImpl的bean,为什么却用了接口UserService?

    • 这里确实也可以跳过接口直接实例化实现类UserServiceImpl的bean

    如:

    	@Autowired 
        UserServiceImpl userServiceImpl;
    
    • 使用接口是因为:
      • AOP编程思想,屏蔽了方法内部逻辑;
      • (通过使用多态)解耦;
      • 接口却可以多实现,方便后面的二次开发或维护
    • 当业务逻辑简单,变更较少,项目自用时,省略掉接口直接使用实现类更简单明了;反之则推荐使用接口;

    Q3、关于注解和xml配置的区别 以及 @Service的具体作用

    放一个大佬的传送: 点击前往

    重点做一下@Service的的笔记:

    在实体类上没有使用@Service的话,spring对应的xml中需要如下配置:

     <?xml version="1.0" encoding="UTF-8"?>
     <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
          xmlns="http://www.springframework.org/schema/beans"  
          xmlns:context="http://www.springframework.org/schema/context"  
          xsi:schemaLocation="http://www.springframework.org/schema/beans 
              http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
              http://www.springframework.org/schema/context
              http://www.springframework.org/schema/context/spring-context-4.2.xsd">
          
         <context:component-scan base-package="com.xrq" />
         
         <bean id="zoo" class="com.xrq.bean.Zoo" />
         <bean id="tiger" class="com.xrq.domain.Tiger" />
         <bean id="monkey" class="com.xrq.domain.Monkey" />
     </beans>
    

    因为spring的配置文件里面还有12行~14行三个bean,下一步的简化是把这三个bean也给去掉,使得spring配置文件里面只有一个自动扫描的标签,增强Java代码的内聚性并进一步减少配置文件。

    使用@Service 后:

    java实体类:

    @Service
    public class Zoo
    {
        @Autowired
        private Tiger ztiger;
        
        @Autowired
        private Monkey zmonkey;
    
    }
    
    @Service
    public class Tiger
    {
        private String tigerName;
    }
    
    @Service
    public class Monkey
    {
        private String monkeyName;
    }
    

    xml中:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
        xmlns="http://www.springframework.org/schema/beans"  
        xmlns:context="http://www.springframework.org/schema/context"  
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-4.2.xsd">
        
        <context:component-scan base-package="com.xrq" />
        
    </beans>
    

    最后感谢一下今天学习的原博主:点击前往

    在放一篇自己感兴趣的文章:传送


    补充

    发现可能对于@AutoWire 和@Resource的理解不够立体,下面再做一些说明

    @Service
    public class UserServiceImpl implements UserService{
    
    	@Override
    	public User findByUsername(String username) {
    		return username;
    	}
    }
    
    • @AutoWire //当使用这个注入的时候上面的 UserServiceImpl 只需要这样写 @Service,这样就会自动找到UserService这个类型以及他的子类型。UserServiceImpl 实现了UserService这个接口,所以能够找到它。不过这样有一个缺点,就是当UserService实现类有两个以上的时候,这个时候会找哪一个呢,这就造成了冲突,所以要用@AutoWire注入的时候要确保UserService只有一个实现类。

    • @Resource 默认情况下是按照名称进行匹配,如果没有找到相同名称的Bean,则会按照类型进行匹配,。但这里还是有缺点,首先,根据这个注解的匹配效果可以看出,它进行了两次匹配,也就是说,如果你在UserService这个类上面这样写注解,@Service,它会怎么找呢,首先是找相同名字的,如果没有找到,再找相同类型的,而这里的@Service没有写名字,这个时候就进行了两次搜索,显然,速度就下降了许多。

      **也许你还会问,这里的@Service本来就没有名字,肯定是直接进行类型搜索啊。其实不是这样的,UserServiceImpl 上面如果有@Service,默认的名字是这个userServiceImpl,注意看,就是把类名前面的大写变成小写,就是默认的Bean的名字了。 **

      @Resource根据名字搜索是这样写@Resource("userService"),如果你写了这个名字叫userService,那么UserServiceImpl上面必须也是这个名字,不然还是会报错。



    (以上资料内容侵删)
    转载时请告知(以上资料内容侵删)
    每个人都知道的,哪怕已经很糟糕了但是努力生活依旧很重要。
  • 相关阅读:
    PHP实现---汉字简体繁体转换
    js对象中的回调函数
    常用js正则
    复合sql
    恢复和去掉所有表约束
    小心as"陷阱"(c#)
    由“js跨域”想到"AJAX也不一定要XMLHttpRequest"
    jsonp与跨域
    关于js的string的3个函数slice,substring,substr对比
    英语etc怎么发音、单词来历
  • 原文地址:https://www.cnblogs.com/ppppian2020/p/13040312.html
Copyright © 2011-2022 走看看