Spring注解:自动装配(@Autowired+@Qualifier+@Primary、@Resource、@Inject)

文章目录

    • 一、概念
      • 1.1 控制反转:lOC(Inversion Of Control)
      • 1.2 依赖注入:DI(Dependency Injection)
      • 1.3 自动装配
    • 二、前提
    • 三、@Autowired注解的使用
      • 3.1 @Autowired自动装配
      • 3.2 @Autowired+@Qualifier
      • 3.3 @Autowired+@Primary
      • 3.4 @Autowired细节
        • 3.4.1 其它用法
        • 3.4.2 @Autowired可以省略的两种情况
    • 四、@Resource和@Inject注解的使用
      • 4.1 @Resource自动装配
      • 4.2 @Inject自动装配
    • 五、总结

一、概念

1.1 控制反转:lOC(Inversion Of Control)

主动式:要什么资源我们自己创建即可。过去采用的方式。

被动式:资源不是由我们自己创建,而是交给一个容器来创建和设置,我们直接拿来用。Spring采用的方式。

1.2 依赖注入:DI(Dependency Injection)

Spring中有个容器,容器能知道哪个组件(类)运行的时候,需要的另外一个组件(类)。容器通过反射的形式,将容器中准备好的组件注入当前组件中。

控制反转(IOC)是一种思想,依赖注入(DI)是一种实现。

1.3 自动装配

在传统的依赖注入配置中,我们必须要明确要给属性装配哪一个bean的引用,一旦bean很多,就不好维护了。

基于这样的场景,Spring使用注解进行自动装配,来解决这个问题。自动装配就是开发人员不必知道具体要装配哪个bean的引用,这个识别的工作会由Spring来完成。自动装配是为了将依赖注入“自动化”的一个简化配置的操作。


二、前提

首先要清楚组件(类)注册到Spring容器后的类型和name,方便下面的理解。

可以参考:https://blog.csdn.net/qq_42780289/article/details/107884738


三、@Autowired注解的使用

3.1 @Autowired自动装配

1)容器中同类型只有一个组件的情况

默认优先按照类型去容器中找对应的组件,找到就赋值。具体看下面的例子:

  • 组件1

    @Service
    public class BookService {
           
    
    }
    

    类型为BookService,name为bookService。

  • 测试

        @Autowired
        BookService bookService;
    
        @Test
        void MyTest() {
           
            System.out.println(bookService);
        }
    

    这里@Autowired先以属性的类型 BookService 去容器中找对应的组件,找到只有一个该类型的组件,成功!

2)容器中同类型有多个组件的情况

如果找到多个相同类型的组件,再将属性的名称作为组件的name去容器中查找。具体看下面的例子:

  • 组件1

    @Service
    public class BookService {
           
    
    }
    

    类型为BookService,name为bookService。

  • 组件2

    @Configuration
    public class MainConfigOfAutowired {
           
    
        @Bean
        public BookService bookService01() {
           
            return new BookService();
        }
    
    }
    

    类型为BookService,name为bookService01。

  • 测试

        @Autowired
        BookService bookService;
    
        @Autowired
        BookService bookService01;
    
        @Test
        void MyTest() {
           
            System.out.println(bookService);
            System.out.println(bookService01);
        }
    

    第一个@Autowired先以属性的类型 BookService 去容器中找对应的组件,找到有两个该类型的组件;接着将属性的名称 bookService 作为组件的name去容器中查找,找到组件1,成功!

    第二个@Autowired同理也可以找到组件2。

3)用类型和name都找不到组件

找不到就会报错。但是也可以使用@Autowired(required=false),找不到就赋值为空。

3.2 @Autowired+@Qualifier

使用@Qualifier指定需要装配的组件的name,而不是使用属性的类型或属性的名称。具体看下面的例子:

  • 组件1

    @Service
    public class BookService {
           
    
    }
    

    类型为BookService,name为bookService。

  • 组件2

    @Configuration
    public class MainConfigOfAutowired {
           
    
        @Bean
        public BookService bookService01() {
           
            return new BookService();
        }
    
    }
    

    类型为BookService,name为bookService01。

  • 测试

        @Qualifier("bookService01")
        @Autowired
        BookService bookService;
    
        @Test
        void MyTest() {
           
            System.out.println(bookService);
        }
    

    使用@Qualifier(“bookService01”)明确指定name后,@Autowired不再看属性的类型或属性的名称,直接用 bookService01 作为组件的name去容器中查找,找到组件2,成功!

3.3 @Autowired+@Primary

让Spring进行自动装配的时候,默认使用首选(用@Primary指定)的bean。具体看下面的例子:

  • 组件1

    @Service
    public class BookService {
           
    
    }
    

    类型为BookService,name为bookService。

  • 组件2

    @Configuration
    public class MainConfigOfAutowired {
           
    
        @Primary
        @Bean
        public BookService bookService01() {
           
            return new BookService();
        }
    
    }
    

    类型为BookService,name为bookService01。

  • 测试1

        @Autowired
        BookService bookService;
    
        @Test
        void MyTest() {
           
            System.out.println(bookService);
        }
    

    因为组件2使用了@Primary注解标注,所以@Autowired不再看属性的类型或属性的名称,直接就找到组件2,成功!

  • 测试2

        @Qualifier("bookService")
        @Autowired
        BookService bookService;
    
        @Test
        void MyTest() {
           
            System.out.println(bookService);
        }
    

    虽然组件2使用了@Primary注解标注,但是使用@Qualifier()明确指定后,@Primary就不起作用了,所以还是直接用指定的 bookService 作为组件的name去容器中查找,找到组件1,成功!

3.4 @Autowired细节

3.4.1 其它用法

@Autowired可以标注在,构造器、参数、方法、属性上,都是从容器中获组件并赋值。

1)标注在属性上

上面已经谈论了很多,这里就不说了。

2)标注在方法上

@Component
public class Bookshelf {
     
    private Book book;

    public Book getBook() {
     
        return book;
    }

    @Autowired
    public void setBook(Book book) {
     
        this.book = book;
    }
}

@Autowired标注在方法上,容器在创建 Bookshelf 对象时,会自动调用该方法从ioc容器中获取 Book 组件,注意该方法也会被执行一次。

3)标注在构造器上

@Component
public class Bookshelf {
     
    private Book book;

    @Autowired
    public Bookshelf(Book book) {
     
        this.book = book;
    }

    public Book getBook() {
     
        return book;
    }

    public void setBook(Book book) {
     
        this.book = book;
    }
}

这里@Autowired标注在构造器上,容器在创建 Bookshelf 对象时,会先调用构造器从ioc容器中获取 Book 组件。

4)标注在参数上

@Configuration
public class MyConfig {
     

    @Bean
    public Bookshelf bookshelf(@Autowired Book book) {
     
        return new Bookshelf(book);
    }
}

这里@Autowired标注在参数上,在向容器注册 Bookshelf 组件时要用到 Book 组件,所以会先从ioc容器中获取 Book 组件,再进行注册。

3.4.2 @Autowired可以省略的两种情况

1)标在构造器上的@Autowired可以省略

@Component
public class Bookshelf {
    private Book book;

    public Bookshelf(Book book) {
        this.book = book;
    }

    public Book getBook() {
        return book;
    }

    public void setBook(Book book) {
        this.book = book;
    }
}

如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,因为构造器要用的组件,都是从容器中获取。

2)@Bean标注方法时,参数的@Autowired可以省略

@Configuration
public class MyConfig {
     

    @Bean
    public Bookshelf bookshelf(Book book) {
     
        return new Bookshelf(book);
    }
}

这里@Bean标注的方法注册组件的时候,方法参数的值可以直接从容器中获取。


四、@Resource和@Inject注解的使用

Spring还支持使用@Resource(JSR250)和@Inject(JSR330)。

4.1 @Resource自动装配

  • 可以和@Autowired一样可以实现自动装配功能。

  • 默认是按照属性的名称来进行装配的。也可以指定name,比如@Resource(name="")。

  • 没有类似@Autowired(reqiured=false)的功能,也不支持@Primary功能。

4.2 @Inject自动装配

  • 需要导入javax.inject的包。

    <dependency>
        <groupId>javax.injectgroupId>
        <artifactId>javax.injectartifactId>
        <version>1version>
    dependency>
    
  • 和@Autowired一样可以实现自动装配功能。

  • 和@Autowired一样,先按照属性的类型查找,如果有多个同类型的组件,再按照属性的名称进行查找。

  • 没有类似@Autowired(reqiured=false)的功能,但是支持@Primary功能。


五、总结

Spring支持使用@Autowired注解,也支持使用@Resource(JSR250)和@Inject(JSR330)注解。

其中@Autowired是Spring框架中的注解,而@Resource(JSR250)和@Inject(JSR330)是java规范的注解。三者的用法前面都有讲,@Autowired注解的功能是最强大的。

你可能感兴趣的:(SSM+SpringBoot,spring,注解,自动装配)