zoukankan      html  css  js  c++  java
  • Spring学习(六)bean装配详解之 【通过注解装配 Bean】【基础配置方式】

    通过注解装配 Bean

    1、前言

    优势

    1.可以减少 XML 的配置,当配置项多的时候,XML配置过多会导致项目臃肿难以维护

    2.功能更加强大,既能实现 XML 的功能,也提供了自动装配的功能,采用了自动装配后,程序猿所需要做的决断就少了,更加有利于对程序的开发,这就是“约定优于配置”的开发原则

    IOC发现Bean的两种方式

    组件扫描:通过定义资源的方式,让 Spring IoC 容器扫描对应的包,从而把 bean 装配进来。

    自动装配:通过注解定义,使得一些依赖关系可以通过注解完成。

    注解分为两类

      一类是使用Bean,即是把已经在xml文件中配置好的Bean拿来用,完成属性、方法的组装;比如@Autowired , @Resource,可以通过byTYPE(@Autowired)、byNAME(@Resource)的方式获取Bean;

      一类是注册Bean,@Component , @Repository , @ Controller , @Service , @Configration这些注解都是把你要实例化的对象转化成一个Bean,放在IoC容器中,等你要用的时候,它会和上面的@Autowired , @Resource配合到一起,把对象、属性、方法完美组装。

    2、使用@Compoent 装配 Bean

    我们把之前创建的 Student 类改一下:

    package pojo;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    @Component(value = "student1")
    public class Student {
    
        @Value("1")
        int id;
        @Value("student_name_1")
        String name;
    
        // getter and setter
    }

     解释一下:

    @Component注解:

      表示 Spring IoC 会把这个类扫描成一个 bean 实例,而其中的 value 属性代表这个类在 Spring 中的 id,这就相当于在 XML 中定义的 Bean 的 id:<bean id="student1" class="pojo.Student" />,也可以简写成 @Component("student1"),甚至直接写成 @Component ,对于不写的,Spring IoC 容器就默认以类名来命名作为 id,只不过首字母小写,配置到容器中。

    @Value注解:

      表示值的注入,跟在 XML 中写 value 属性是一样的。

        这样我们就声明好了我们要创建的一个 Bean,就像在 XML 中写下了这样一句话:

    <bean name="student1" class="pojo.Student">
        <property name="id" value="1" />
        <property name="name" value="student_name_1"/>
    </bean>

       但是现在我们声明了这个类,并不能进行任何的测试,因为 Spring IoC 并不知道这个 Bean 的存在,这个时候我们可以使用一个 StudentConfig 类去告诉 Spring IoC :

    package pojo;
    import org.springframework.context.annotation.ComponentScan;
    
    @ComponentScan
    public class StudentConfig {
    }

    这个类十分简单,没有任何逻辑,但是需要说明两点:

    1、该类和 Student 类位于同一包名下

    2、@ComponentScan注解:

    代表进行扫描,默认是扫描当前包的路径,扫描所有带有 @Component 注解的 POJO。

    PS:也可以用XML来配置扫描路径,不过推荐使用注解的形式

     

      这样一来,我们就可以通过 Spring 定义好的 Spring IoC 容器的实现类——AnnotationConfigApplicationContext 去生成 IoC 容器了:

    ApplicationContext context = new AnnotationConfigApplicationContext(StudentConfig.class);
    Student student = (Student) context.getBean("student1", Student.class);
    student.printInformation();

      这里可以看到使用了 AnnotationConfigApplicationContext 类去初始化 Spring IoC 容器,它的配置项是 StudentConfig 类,这样 Spring IoC 就会根据注解的配置去解析对应的资源,来生成 IoC 容器了。

    明显的弊端:

    • 对于 @ComponentScan 注解,它只是扫描所在包的 Java 类,但是更多的时候我们希望的是可以扫描我们指定的类
    • 上面的例子只是注入了一些简单的值,测试发现,通过 @Value 注解并不能注入对象

    @Component 注解存在着两个配置项:

    basePackages:它是由 base 和 package 两个单词组成的,而 package 还是用了复数,意味着它可以配置一个 Java 包的数组,Spring 会根据它的配置扫描对应的包和子包,将配置好的 Bean 装配进来

    basePackageClasses:它由 base、package 和 class 三个单词组成,采用复数,意味着它可以配置多个类, Spring 会根据配置的类所在的包,为包和子包进行扫描装配对应配置的 Bean

    我们来试着重构之前写的 StudentConfig 类来验证上面两个配置项:

    package pojo;
    import org.springframework.context.annotation.ComponentScan;
    
    @ComponentScan(basePackages = "pojo")//配置扫描pojo包
    public class StudentConfig {
    }
    
    //  —————————————————— 【 宇宙超级无敌分割线】—————————————————— 
    package pojo;
    
    import org.springframework.context.annotation.ComponentScan;
    
    @ComponentScan(basePackageClasses = pojo.Student.class)//配置扫描pojo包下名为Student的类
    public class StudentConfig {
    }

    对于 【basePackages】 和 【basePackageClasses】 的选择问题:

      【basePackages】 的可读性会更好一些,所以在项目中会优先选择使用它,但是在需要大量重构的工程中,尽量不要使用【basePackages】,因为很多时候重构修改包名需要反复地配置,而 IDE 不会给你任何的提示,而采用【basePackageClasses】会有错误提示。

    3、自动装配——@Autowired

    定义:由 Spring 自己发现对应的 Bean,自动完成装配工作的方式(根据类型查找

    例子解析:

    1.先在 Package【service】下创建一个 StudentService 接口:

    package service;
    
    public interface StudentService {
        public void printStudentInfo();
    }

    PS:使用接口是 Spring 推荐的方式,这样可以更为灵活,可以将定义和实现分离

    2.为上面的接口创建一个 StudentServiceImp 实现类:

    @Component("studentService")//表示IoC把这个类扫描成一个bean实例(这里简写了,括号内等同于XML配置方式时的id)
    public class StudentServiceImp implements StudentService {
    
        @Autowired//Spring自己发现bean并装配
        private Student student = null;
    
        public void printStudentInfo() {
            System.out.println("学生的 id 为:" + student.getName());
            System.out.println("学生的 name 为:" + student.getName());
        }
    }

    3.编写测试类:

    // 第一步:修改 StudentConfig 类,告诉 Spring IoC 在哪里去扫描它:
    package pojo;
    
    import org.springframework.context.annotation.ComponentScan;
    
    @ComponentScan(basePackages = {"pojo", "service"})
    public class StudentConfig {
    }
    
    // 或者也可以在 XML 文件中声明去哪里做扫描
    <context:component-scan base-package="pojo" />
    <context:component-scan base-package="service" />
    
    // 第二步:编写测试类:
    package test;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import pojo.StudentConfig;
    import service.StudentService;
    import service.StudentServiceImp;
    
    public class TestSpring {
    
        public static void main(String[] args) {
            // 通过注解的方式初始化 Spring IoC 容器
            ApplicationContext context = new AnnotationConfigApplicationContext(StudentConfig.class);
            StudentService studentService = context.getBean("studentService", StudentServiceImp.class);
            studentService.printStudentInfo();
        }
    }

    小结:

      @Autowired 注解表示在 Spring IoC 定位所有的 Bean 后,再根据类型寻找资源,然后将其注入。

      过程:定义 Bean ——》 初始化 Bean(扫描) ——》 根据属性需要从 Spring IoC 容器中搜寻满足要求的 Bean ——》 满足要求则注入

      问题: IoC 容器可能会寻找失败,此时会抛出异常(默认情况下,Spring IoC 容器会认为一定要找到对应的 Bean 来注入到这个字段,但有些时候并不是一定需要,比如日志)

      解决: 通过配置项 required 来改变,比如 @Autowired(required = false),该属性可控制IOC容器找不到Bean时不报错。

      PS:@Autowired 注解不仅仅能配置在属性之上,还允许方法配置,常见的 Bean 的 setter 方法也可以使用它来完成注入,总之一切需要 Spring IoC 去寻找 Bean 资源的地方都可以用到

  • 相关阅读:
    Python 爬虫js加密破解(一) 爬取今日头条as cp 算法 解密
    Python 爬虫实例(2)—— 爬取今日头条
    Python 爬虫实例(1)—— 爬取百度图片
    python 操作redis之——HyperLogLog (八)
    python 操作redis之——有序集合(sorted set) (七)
    Python操作redis系列之 列表(list) (五)
    Python操作redis系列以 哈希(Hash)命令详解(四)
    Python操作redis字符串(String)详解 (三)
    How to Install MySQL on CentOS 7
    Linux SSH远程文件/目录 传输
  • 原文地址:https://www.cnblogs.com/riches/p/11521428.html
Copyright © 2011-2022 走看看