Spring注解驱动开发学习总结8:自动装配注解@Autowire、@Resource、@Inject
1、自动装配@Autowire、@Resource、@Inject
1、可以使用@Autowire注解自动注入组件
1.1 自动装配@Autowire注解,默认一定存在该bean,如果不存在就会报错。可以使用将参数required设置为false,表示该bean可以不存在:@Autowired(required = false)
1.2 默认优先按照类型去容器中找对应的组件。如果找到了多个相同类型的组件,再将属性的名称作为组件的id去容器中查找。
1.2.1 如果有多个同类型组件,可以使用@Qualifier(“id名称”)注解自动导入指定id名
称的bean。
1.2.2 如果有多个同类型组件,可以在bean上使用@Primary注解。让Spring进行自
动装配的时候,默认使用该bean。
1.3 @Autowire可以放在构造器、参数、方法、属性上。都是自动从容器中取参数组件的值。
1.3.1 标注在方法上:@Bean+方法参数,参数从容器中获取。默认可以不写 @Autowire,效果是一样的,该参数也会自动从容器中获取。
1.3.2 标注在构造器上:如果组件只有一个有参构造器,那么这个有参构造器的
@Autowire可以省略,参数位置的组件也会自动从容器中获取。
1.3.3 标注在参数上:上面已经演示过了。
以下还是以之前构建的bookService,bookDao进行举例。我们会在容器中添加两个同类型的bookDao,然后在bookService中自动导入,从而来测试下使用@Autowire注解自动导入的情况。
2、也可以使用Java规范的注解@Resource和@Inject自动注入组件
2.1 @Resource注解:可以和@Autowire一样实现自动装配功能,默认是按照组件名称进行装配。不支持@Primary功能,也没有@Autowired(required = false)的功能
2.2 @Inject注解:和@Autowire功能一样,同样也没有@Autowired(required = false)的功能。同时需要导入javax.inject的依赖包
1.1 构建bookDao
构建bookDao:com/example/dao/BookDao.java。
在BookDao上添加@Repository注解,可以将BookDao注入容器。
package com.example.dao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
@Repository
public class BookDao {
String label="1";
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
@Override
public String toString() {
return "BookDao{" +
"label='" + label + '\'' +
'}';
}
}
1.2 构建bookService
构建bookService:com/example/service/BookService.java
在booService中自动注入BookDao类型的组件。
package com.example.service;
import com.example.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
@Service
public class BookService {
@Autowired(required = false)
BookDao bookDao;
public void print() {
System.out.println("BookService_print: " + bookDao);
}
}
1.3 构建配置文件
构建配置文件:com/example/config/MainConfigAutowire.java
在配置文件中再注入一个类型为BookDao,id为bookDao2的bean。
package com.example.config;
import com.example.dao.BookDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
@ComponentScan(value = {"com.example.service", "com.example.dao"})
public class MainConfigAutowire {
@Bean("bookDao2")
public BookDao bookDao() {
BookDao bookDao = new BookDao();
bookDao.setLabel("2");
return bookDao;
}
}
1.4 同类型组件测试一
由1.1-1.3可以看到,目前容器中有2个BookDao组件:bookDao和bookDao2。
构建测试方法:testAutowire。测试下BookService中自动导入的组件是哪一个bean。
@Test
public void testAutowire() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigAutowire.class);
System.out.println("\nioc容器已创建完成\n");
BookService bean = applicationContext.getBean(BookService.class);
bean.print();
}
以下是运行结果。
可以看到,@Autowired注解默认优先按照类型去容器中找对应的组件。如果找到了多个相同类型的组件,再将属性的名称作为组件的id去容器中查找。因此,这里找到的是bookDao组件,该组件的label=1.
1.5 同类型组件测试二(使用@Qualifier指定id名称)
此时修改bookService,在bookService上使用@Qualifier注解,指定使用id为bookDao2的BookDao组件。
package com.example.service;
import com.example.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
@Service
public class BookService {
@Qualifier("bookDao2")
@Autowired(required = false)
BookDao bookDao;
public void print() {
System.out.println("BookService_print: " + bookDao);
}
}
再次运行测试方法:testAutowire。可以看到这一次bookService确实自动导入的是bookDao2的组件。
1.6 同类型组件测试三(使用@Primary)
此时将上一步的@Qualifier注解去掉,将配置文件(MainConfigAutowire.java)中id为bookDao2的bean添加@Primary注解,表示默认首选使用这个bean。
package com.example.config;
import com.example.dao.BookDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
@ComponentScan(value = {"com.example.service", "com.example.dao"})
public class MainConfigAutowire {
@Primary
@Bean("bookDao2")
public BookDao bookDao() {
BookDao bookDao = new BookDao();
bookDao.setLabel("2");
return bookDao;
}
}
再次运行测试方法:testAutowire。可以看到这一次bookService再次自动导入的依然是bookDao2的组件。
1.7 同类型组件测试四(使用@Resource)
在bookService中不再使用@Autowired自动导入,同样可以改为使用Java规范的@Resource注解注入。
虽然@Resource不支持@Primary功能,但是它同样可以指定bena的id名称:bookDao2。
package com.example.service;
import com.example.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.inject.Inject;
@Service
public class BookService {
// @Qualifier("bookDao2")
// @Autowired(required = false)
// @Inject
@Resource(name = "bookDao2")
BookDao bookDao;
public void print() {
System.out.println("BookService_print: " + bookDao);
}
}
再次运行测试方法:testAutowire。可以看到这一次bookService再次自动导入的依然是bookDao2的组件。
1.8 同类型组件测试五(使用@Inject)
不使用@Autowired和@Resource注解,还可以使用@Inject注解,它的功能与@Autowired一致。
首先需要在pom文件中导入javax.inject依赖包:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>spring-annotation</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
</dependencies>
</project>
然后修改bookService:
package com.example.service;
import com.example.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.inject.Inject;
@Service
public class BookService {
// @Qualifier("bookDao2")
// @Autowired(required = false)
@Inject
// @Resource(name = "bookDao2")
BookDao bookDao;
public void print() {
System.out.println("BookService_print: " + bookDao);
}
}
再次运行测试方法:testAutowire。由于我们在bookDao2的组件上添加了@Primary注解,可以看到这一次bookService再次自动导入的依然是bookDao2的组件。