• (II)第十四节:使用@Autowired 注解自动装配


    一、分析

            Controller 组件中往往需要用到 Service 组件的实例,Service 组件往往需要用到 Repository 组件的实例。
            既然通过注解可以标识一个 Spring 组件,那么Spring 也应该可以通过注解的方式帮我们实现属性的装配。

    二、实现依据

            在指定要扫描的包时,<context:component-scan> 元素会自动注册一个 bean 的后置处理器:AutowiredAnnotationBeanPostProcessor 的实例。该后置处理器可以自动装配标记了 @Autowired、@Resource 或 @Inject 注解的属性。
     

    三、@Autowired 注解使用

      applicationContext.xml

    <context:component-scan base-package="com.achang"></context:component-scan>

      BookDao

    @Repository
    public class BookDao {
        public void saveBook() {
            System.out.println("保存了一本书");
        }
    }

      BookService

    @Service
    public class BookService {
        @Autowired
        private BookDao bookDao;
    
        public void save(){
            System.out.println("正在调用Dao保存图书。。。。");
            bookDao.saveBook();
        }
    }

      BookServlet

    @Controller
    public class BookServlet {
        //自动装配:自动为这个属性赋值
        @Autowired
        private BookService bookService;
        
        public void doGet(){
            bookService.save();
        }
    }

      测试:

    public class IOCTest {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        @Test
        public void test2(){
            BookServlet bookServlet = (BookServlet) ioc.getBean("bookServlet");
            bookServlet.doGet();
            //正在调用Dao保存图书。。。。
            //保存了一本书
    
        }

      

      使用 @Qualifier 可以指定要装配的组件的名字 id;

      @Autowired 的自动装配就是一定装配上,可以设置 required 属性,默认为 true,设置为 false 后,如果在容器中找不到就不进行装配,且不会报错。

    @Controller
    public class BookServlet {
    
        @Qualifier(value = "bookServiceExt")
        @Autowired(required = false)
        private BookService bookService;
    
        public void doGet() {
            bookService.save();
        }
    }

    四、原理和区别

      (1)先按照类型去找,如果找到了,装配成功;

      (2)如果资源类型的bean不止一个,默认根据@Autowired注解标记的成员变量名作为id查找bean,进行装配;

      (3)如果根据成员变量名作为id还是找不到bean,可以使用@Qualifier注解明确指定目标bean的id;

      (4)@Autowired注解的required属性指定某个属性允许不被设置;

      @Autowired 原理【***】

        <!--@Autowired原理
        @Autowired
        private BookService bookService;
            1、先按照类型去容器找到对应的组件; bookService = ioc.getBean("BookService.class");
                ①匹配成功;装配
                ②匹配失败;抛出异常报错(NoSushBeanDefinitionException)
                ③匹配多个;
                    按照变量名作为id继续匹配
                        1)匹配成功;装配
                        2)匹配失败;抛出异常报错
                            失败原因:Spring会使用id在容器中匹配
                            【可使用@Qualifier("xxxXxx")指定一个新id匹配】
                                1)匹配成功;装配
                                2)匹配失败;抛出异常报错
    
              发现AutoWired标注的自动装配的属性默认是一定装配上,任何情况下没匹配就是抛出异常报错
                    找到就装配,找不到就拉倒
                    @Autowired(required=false):默认为true,给为匹配上的赋值为null

      先按照类型找,找到装配,找不到就按变量名做id找,找到装配,找不到抛异常。

      可以用@Qualifier指定id去匹配;此注解可修饰参数

    五、在形参位置使用 @Qualifier 注解

       观看源码,可以看到 Autowired 注解可以使用在构造器,字段,方法和注解上面。

       Qualifier 注解可以使用在字段,方法,参数,类和注解上面。

      案例:

        /**
         * 方法上有 @Autowired 注解
         *  1. 这个方法也会在 bean 创建的时候自动运行
         *  2. 这个方法的每一个参数都会自动注入值
         *  3. 可以使用Qualifier注解给参数添加注解
         *  4.  使用 required 属性表示是否必须要装配
         * @param bookDao
         */
        @Autowired(required = false)
        public void saveBook(BookDao bookDao, @Qualifier("bookService") BookService bookService) {
            System.out.println("Spring运行了这个方法" + bookDao + "===" + bookService);
        }

    五、@Autowired 注解

        ① 该注解根据类型实现自动装配;
                ② 构造器、普通字段(即使是非 public)、一些具有参数的方法都可以应用 @Autowired 注解;
                ③ 默认情况下,所有使用 @Autowired 注解的属性都需要被设置,当 Spring 找不到匹配的 bean 装配属性时,会抛出异常;
                ④ 若某一属性允许不被设置,可以设置@Autowired 注解的required 属性为 false。 
                ⑤ 默认情况下,当 IOC 容器里存在多个类型兼容的 bean 时,Spring 会尝试匹配 bean 的 id是否与变量名相同,如果相同则进行装配,如果 bean 的 id 值不相同,通过类型的自动装配将无法工作。
                    此时可以在 @Qualifier 注解里提供 bean 的名称,Spring 甚至允许在方法的形参上标注 @Qualifier 注解以指定注入 bean 的名称;
                ⑥ @Autowired 注解也可以应用在数组类型的属性上,此时 Spring 将会把所有匹配 bean 进行自动装配;
                ⑦ @Autowired 注解也可以应用在集合属性上,此时 Spring 读取集合的类型信息,然后自动装配所有与之兼容的 bean;
                ⑧ @Autowired 注解用在 java.util.Map 上时,若该 Map 的键值为 String,那么 Spring 将自动装配与值类型兼容的 bean 作为值,并以 bean 的 id 值作为键。

    六、@Autowired和@Resource、@Inject的区别

      @Autowired、@Resource、@Inject都可以作为注入注解

    @Autowired:最强大;Spring的注解
    	①扩展性差,依赖Spring容器框架
    	
    @Resource:j2ee;java的标准【jdk标准】
    	①扩展性强:切换成另一个容器框架,其还会可以使用
    	
    	
    【@Inject:在EJB环境下使用()】
    

      @Resource 注解要求提供一个 bean 名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为 bean 的名称

       @Inject 和 @Autowired 注解一样也是按类型注入匹配的 bean,但没有 required 属性。

       

    七、代码示例

      表示控制器层:

    //@Controller(value="userCtrl")        //使用 value 属性来给自动生成的 bean 指定 id,默认是类名的首字母表小写
    @Controller("userCtrl")                // 如果只设置 value 属性,value可以省略;但如果有多个属性,各个属性间用逗号分隔  
    public class UserController {
         
         @Autowired(required=true)           //自动装配,required 该属性表示是否必须自动装配成功
         private IUserService userService;   // true 表示 IOC 容器中必须有一个 bean 与该属性相匹配,然后完成自动装配,不然 Spring 报错
                                             // false 表示 IOC 容器中可以没有与该属性匹配的 bean,即不必自动装配成功,Spring 也不会报错
         public void addUser() {
             userService.addUser();
         }
         public UserController() {
             super();
         
             System.out.println("UserController构造器");
         }
         
    }

      业务逻辑层:

    @Service
    public class UserServiceImpl implements IUserService {
         
         @Autowired
         private IUserDao userDao;
         
         /*
         @Autowired                                     //  这两个注解必须同时使用
         @Qualifier(value="userDaoMybatisImpl")         // 当有多个同类型的bean时,使用该注解指定 bean 的id来给形参赋值,与方法名无关
         public void setUserDao(IUserDao userDao) {
             this.userDao = userDao;
         }
         */
         
         @Override
         public void addUser() {
             userDao.addUser();
         }
         public UserServiceImpl() {
             super();
             System.out.println("UserServiceImpl构造器");
         }
         
    }

      持久层:

    类一:
    @Repository
    public class UserDaoImpl implements IUserDao {
         @Override
         public void addUser() {
             System.out.println("UserDaoImpl:添加成功");
         }
         public UserDaoImpl() {
             super();
             System.out.println("UserDaoImpl构造器");
         }
         
    }
    
    类二:
    @Repository
    public class UserDaoMybatisImpl implements IUserDao {
         @Override
         public void addUser() {
             System.out.println("添加成功");
         }
         public UserDaoMybatisImpl() {
             super();
             System.out.println("UserDaoMybatisImpl构造器");
         }
    }

    八、注解配置 bean 总结

    基于注解的组件化管理:
            @Component,@Controller(控制层),@Service(业务逻辑层),@Repository(持久层)
            这四个注解的功能完全相同,都用来标识组件,只是在实际开发中,要在实现不同功能的类上加上相应的注解,以便区分;
        
        完成组件化管理的过程:
            1、在需要被 Spring 管理的类上加上对应的注解
            2、在配置文件中通过 <context:component-scan> 标签对所设置的包结构进行扫描,就会将加上注解的类,作为spring的组件进行加载,
                  组件(即为 Spring 中管理的 bean)
                  作为 Spring 的组件进行加载:会自动在 Spring 的配置文件中生成相对应的bean,这些 bean的 id 默认会以类的首字母小写为值,也可以通过注解的 value 属性来给自动生成的 bean 指定 id。(如:@Controller(value="userCtrl") 或 @Controller("userCtrl"),只有 value 属性时,value 可以省略)
            
         使用注解自动装配:
                自动装配:在需要赋值的非字面量属性上,加上 @Autowired 注解,就可以在spring容器中,通过不同的方式匹配到相对应的bean;
                @Autowired 装配时,默认使用 byType 的方式进行匹配,此时要求spring容器中只有一个能够为其赋值,否则会报错
                                                    当byType 实现不了装配时,会自动切换到 byName 的方式匹配,此时要求spring容器中,有一个bean的id和属性名一致
                 使用@Autowired 自动装配时,如果匹配到多个能够赋值的 bean,可以使用 @Qualifier(value="beanId")  来指定一个 bean 给属性赋值;
                @Autowired 和 @Qualifier(value="beanId")  可以一起作用于带形参方法上,此时,@Qualifier(value="beanId") 将用 value 所指定 bean 作用于 方法的形参
     
  • 相关阅读:
    Isolation Forest原理总结
    python 黑客书籍 ——扫描+暴力破解
    DNS解析过程
    DNS污染——domain name的解析被劫持了返回无效的ip
    leetcode 427. Construct Quad Tree
    todo
    leetcode 172. Factorial Trailing Zeroes
    leetcode 26. Remove Duplicates from Sorted Array
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(3月3日)
    北京Uber优步司机奖励政策(3月2日)
  • 原文地址:https://www.cnblogs.com/niujifei/p/15418453.html
Copyright © 2020-2023  润新知