zoukankan      html  css  js  c++  java
  • 装配SpringBean(五)--注解装配之自动装配

    在spring ioc容器中,spring要先完成bean的定义和生成,然后需要需要注入的资源,在上一篇的扫描组件中就是这样实现的。而自动装配中我们只需要定义和生成一个bean,发现bean的过程将由spring自己完成,它是怎么发现的呢?答案是通过注解@Autowired,这个单词的意思就是自动装配,当我们在一个资源上使用了这个注解之后,spring如果发现这个注解,就会根据对应的类在生成的bean中找到对应的目标完成自动装配,不需要我们自己定义一个配置类告知spring需要扫描的包路径等信息。所以如果注解方式再细分的话,还能分成两种:

    • 注解@Component+java配置
    • 注解@Component+注解@Autowired

    其实在扫描组件方式装配的例子中,我所定义的类它的成员变量都是基本类型,如果碰到引用类型就不太好办,恰好自动装配可以解决这一问题。自动装配实现只需要两步:定义资源-获取资源,同组件扫描方式相比,它少了一步扫描资源的步骤,因为这个是由spring自己完成的。下面举实例说明:

    假设我要在controller层许调用service层的方法,这时候获取service对象我们就可以通过spring的自动装配完成。

    一、定义资源(使用注解@Component)

     1 @Component
     2 public class CoderService {
     3 
     4     private SqlSession sqlSession = null;
     5     private CoderMapper coderMapper = null;
     6 
     7     // insert a coder to database
     8     public void saveCoder(Coder coder) {
     9         try {
    10             sqlSession = MybatisTool.getSqlSession();
    11             coderMapper = sqlSession.getMapper(CoderMapper.class);
    12             int res = coderMapper.insert(coder);
    13             sqlSession.commit();
    14             System.out.println(res > 0 ? "保存成功" : "保存失败");
    15         } catch (Exception e) {
    16             System.out.println("保存失败");
    17         } finally {
    18             if (sqlSession != null) {
    19                 sqlSession.close();
    20             }
    21         }
    22     }
    23 }

    定义bean的时候还是需要用到注解@Component,这样spring ioc容器就能生成对应类的bean实例。

    二、获取资源(使用注解@Autowired)

    1 public class CoderController {
    2     
    3     @Autowired
    4     public CoderService coderService = null;
    5     
    6     public void save(Coder coder) {
    7         coderService.saveCoder(coder);
    8     }
    9 }

    通过上面的注解@Autowired,spring就会自动装配coderService这个bean,这样我们就可以直接在save方法中调用其方法了。

    通过以上两步就能轻松实现bean的装配,不用java配置并告诉spring扫描路径等信息,可见配置的越来越少,这种方式就比较适合含引用变量的bean的装配。它虽然简单好用,但是也有一个缺点,就是歧义性。

    三、自动装配的歧义性

    什么是歧义性呢?因为spring是根据类型在已经生成的所有bean中查找对应的bean实例,如果这个类型是个接口,既然是接口就会有多个实现类,这个时候spring ioc容器岂不是蒙圈了?我找到了这么多,到底选哪个呢?这是不是就出现歧义了呢?spring中提供了两种方式解决这个问题

    • 注解@Primary:用在类上,表示优先使用这个类的bean
    • 注解@Qualifier("组件名"):用在引用变量上,参数组件名是注解Component中的定义的名称

    这样说有些晦涩难懂,直接上代码举例吧:

    1⃣️定义一个接口CoderService

    1 /*
    2  * 定义一个接口,提供coding方法
    3  */
    4 
    5 public interface CoderService {
    6     public void coding();
    7 }

    2⃣️定义两个实现类JavaCoderServiceImpl和PhpCoderServiceImpl并实现CoderService接口

     1 @Component("javaCoderService")
     2 @Primary
     3 public class JavaCoderServiceImpl implements CoderService{
     4 
     5     @Override
     6     public void coding() {
     7         System.out.println("使用java开发");
     8     }
     9 }
    10 
    11 @Component("phpCoderService")
    12 public class PhpCoderServiceImpl implements CoderService {
    13 
    14     @Override
    15     public void coding() {
    16         System.out.println("使用PHP开发");
    17     }
    18 }

    上面的方法类中,两个都使用了@Component注解生成用来生成bean,而JavaCoderServiceImpl类上还有一个注解@Primary用来设置优先级,就是在spring查找到两个相同类型的实例时,优先选择含有@Primary注解的这个。 

    3⃣️自动装配调用方法

     1 @Component("coderController")
     2 public class CoderController {
     3     
     4     @Autowired(required=false)
     5     public CoderService coderService = null;
     6     
     7     public void coding() {
     8         coderService.coding();
     9     }
    10 }

    上面通过@Autowired注解进行自动装配,并设置required为false,意味着不是必须的,以防在找不到时抛出异常,因为默认是true;这种方式只能是控制bean的优先权,并不能容器自己选择合适的类型,这就有了@Qualifier(bean名称)注解,这个注解相当于按bean名称进行装配,它作用于变量上,此时可以删除注解@Primary,装配方式如下:

     1 @Component("coderController")
     2 public class CoderController {
     3     
     4     @Autowired(required=false)
     5     @Qualifier("javaCoderService")
     6     public CoderService coderService = null;
     7     
     8     public void coding() {
     9         coderService.coding();
    10     }
    11 }

    以上就是自动装配方式。

  • 相关阅读:
    C语言丨二维数组常用的4种表示方法
    据说程序员最怕命名!这个 6300 Star 的手册能帮上忙
    C语言基础丨(六)程序结构——分支(选择)结构【2】
    系统管理员应该知道的 20 条 Linux 命令!越早学会越好!
    憋不住了!这8 个 MySQL 陷阱,我不得不说一下...
    记录一次@Around使用不正确造成的StackOverflowError
    【java基础】为何e1==(e1=e2)为false
    《Java程序性能优化》subString()方法的内存泄露
    【爬虫】花瓣采集下载器
    SpringMVC容器加载流程总结
  • 原文地址:https://www.cnblogs.com/hellowhy/p/9715063.html
Copyright © 2011-2022 走看看