美文网首页
SpringBoot 依赖注入IoC和控制反转DI

SpringBoot 依赖注入IoC和控制反转DI

作者: 一起码 | 来源:发表于2020-04-22 17:22 被阅读0次

    Spring最成功的是其提出的理念,而不是技术本身。它所依赖的两个核心理念,一个是控制反转(Inversion of Control,IoC),另一个是面向切面编程(Aspect Oriented Programming,AOP)

    IoC是一种通过描述来生成或者获取对象(Bean)的技术,这个技术不是Spring甚至不是Java独有的。平时最熟悉的是使用new关键字来创建对象,而在Spring中则不是,它是通过描述来创建对象。Spingt Boot中建议使用注解描述生成对象而不是使用XML。

    Spring中把每一个需要管理的对象称为Spring Bean(简称Bean),管理这些Bean的容器称为Spring IoC容器(或者简称IoC容器)。IoC容器具备两个基本的功能:通过描述管理Bean(包括发布和获取Bean)和通过描述完成Bean之间的依赖关系。

    Spring IoC容器总,可以按类型(by type)或者按名称(by name)获取Bean,默认情况下Bean都是以单例存在的。

    IoC装配Bean

    使用@Bean注解装配Bean

    @Configuration
    public class BeanConfig {
        @Bean(name = "user")
        public User initUser() {
            User user = new User();
            user.setUsername("Jack");
            user.setAge(18);
            return user;
        }
    }
    

    @Configuration 表示这是一个Java配置文件,Spring容器会根据它来生成IoC容器去装配Bean
    @Bean 表示将initUser方法返回的POJO装配到IoC容器中,属性name定义Bean的名称,如果没有设置该属性,则默认使用方法名称initUser作为Bean的名称保存到Spring IoC容器中

    通过扫描装配Bean

    如果使用@Bean一个个的装配,将是一件很麻烦的事情,Spring也意识到了这点,允许使用扫描的方式进行装配,使用的注解是@Component和@ComponentScan,@Component标明哪个类被扫描进入Spring IoC容器,而@ComponentScan则是标明采用何种策略扫描装配Bean

    package com.test.example.config;
    
    @Component("user")
    public class User {
        @Value("Jack")
        private String username;
        
        @Value("18")
        private int age;  
    }
    

    @Component标明该类将被Spring IoC容器扫描装配,其中配置的user则是Bean的名称,如果不配置,则IoC容器默认会把类名第一个字母作为小写,其他不变作为Bean名称
    @Value 指定具体的值,使得Spring IoC给予对应的属性注入对应的值

    为了Spring IoC容器装配这个类,调整BeanConfig

    package com.test.example.config;
    
    @Configuration
    @ComponentScan
    public class BeanConfig {
    
    }
    

    @ComponentScan 标明会进行扫描,默认只是扫描BeanConfig所在的当前package和子package,可以观察到User也在该package下面,但是这样设置太不合理,为了更加合理,运行@ComponentScan扫描自定义的包

    @ComponentScan(basePackages = {" com.test.example.pojo"})
    

    包名可以采用正则表达式匹配,但是这个也有不合理的地方,比如不想加载某些Bean,比如定义一个UserService类,将它标记为@Service(该注解已经注入了@Component)服务类,则也会被Spring扫描装配到IoC容器中,如果不希望这些服务类被装配,则可以通过设置excludeFilters

    @ComponentScan(basePackages = {" com.test.example.*", excludeFilters = {@Filter(classes = {Service.class})}})
    

    由于加入excludeFilters设置,则使用@Service注解的服务类不会被扫描注入

    自定义第三方Bean

    实际项目中经常需要引入许多第三方的包,并且希望把第三方包的类对象放入到Spring IoC容器中,这时需要使用@Bean注解

    定义一个数据源

     @Bean(name = "dataSource")
     public DataSource getDataSource() {
        Properties props = new Properties();
        props.setProperty("driver", "com.mysql.jdbc.Driver");
        props.setProperty("url", "jdbc:mysql://localhost:3306/test");
        props.setProperty("username", "root");
        props.setProperty("password", "root");
        
        DataSource dataSource = null;
        try {
            dataSource = BasicDataSourceFactory.createDataSource(props);
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return dataSource;
     }
    

    通过@Bean的name配置Bean名称为“dataSource”,如果不设置name属性,默认会使用方法名称作为Bean名称保存到IoC容器中。

    上半部分主要讨论了Bean如何装载到IoC容器中,对于如何获取以及Bean之间的依赖,在Spring IoC概念中称为依赖注入(Dependency Injection,DI)

    依赖注入DI

    @Autowired

    Spring中最常用注解之一,可以标注属性、方法、参数。

    根据类型(by type)获取Bean,@Autowired是一个默认必须找到对应Bean的注解,如果不确定其标注的属性一定存在并且允许被标注的属性为Null,可以设置required属性为false

    @Autowired(require = false)
    

    消除歧义性 @Primary和@Qualifier

    @Primary是一个修改优先权的注解,其目的当发现有多个同类型的Bean时,高速IoC容器优先使用该注解标记的Bean,但是它也可以被标注到多个Bean上,这时IoC容器还是无法区分要采用哪个Bean实例,此时需要使用@Qualifier的value来进行设置

    @Qualifier和@Autowired组合在一起就是通过类型和名称一起找到Bean,Bean的名称在IoC容器中是唯一的,如

    @Autowired
    @Qualifier("dog")
    private Animal animal = null;
    

    带有参数的构造方法类装配

    public ConstructorAnimal(@Autowired @Qualifier("dog") Animal animal) {
        ...
    }
    

    相关文章

      网友评论

          本文标题:SpringBoot 依赖注入IoC和控制反转DI

          本文链接:https://www.haomeiwen.com/subject/dedwihtx.html