@AutoWired
@Autowired
将会自动从 IoC 容器中查找与标注属性同类型的 bean 注入, 如果容器中有多个相同类型的 bean,将会注入 id
与 属性名相同的那个 bean。
示例
1、创建测试 Dao:
// com.springanno.dao.UserDao
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
}
2、创建测试 Service:
// com.springanno.service.UserService
import com.springanno.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
/**
* 默认情况下,如果容器中没有该属性类型对应的 bean,那么将会抛出异常
* 可通过指定 @Autowired 的属性 required = false 让此次的自动装配不必须,此时容器中如果不存在该类型 bean 就不会抛出异常
*/
@Autowired(required = false)
private UserDao userDao;
public void printDao() {
System.out.println(userDao);
}
}
3、使用注解扫描包:
// com.springanno.config.MainConfig
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.springanno")
public class MainConfig {
}
4、测试:
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
UserService userService = applicationContext.getBean(UserService.class);
System.out.println(userService);
userService.printDao();
/*
com.springanno.service.UserService@60dcc9fe
com.springanno.dao.UserDao@222114ba
*/
@Autowired
不仅可以用在属性上,还可以用在方法上:
// com.springanno.service.UserService
import com.springanno.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private UserDao userDao;
/*
将会从容器中找到与参数类型相同的 bean 传入来执行该方法
*/
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void printDao() {
System.out.println(userDao);
}
}
也可以标注在构造器上:
// com.springanno.service.UserService
import com.springanno.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private UserDao userDao;
/*
将会从容器中找到与参数类型相同的 bean 传入来执行该构造器来创建 UserService 实例
*/
@Autowired
public UserService(UserDao userDao) {
this.userDao = userDao;
}
public void printDao() {
System.out.println(userDao);
}
}
不仅如此,还可以标注在参数上:
// com.springanno.service.UserService
import com.springanno.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private UserDao userDao;
/*
将会从容器中找到与参数类型相同的 bean 传入来执行该构造器来创建 UserService 实例
*/
public UserService(@Autowired UserDao userDao) {
this.userDao = userDao;
}
public void printDao() {
System.out.println(userDao);
}
}
如果当前组件只有一个有参构造器, @Autowired
可以省略不写:
// com.springanno.service.UserService
import com.springanno.dao.UserDao;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private UserDao userDao;
/*
当前组件只有一个有参构造器
将会从容器中找到与参数类型相同的 bean 传入来自动执行该构造器来创建 UserService 实例
*/
public UserService (UserDao userDao) {
this.userDao = userDao;
}
public void printDao() {
System.out.println(userDao);
}
}
通过 @Bean
标注方法注册 bean 时,该方法的参数也会默认从容器中获取,看如下示例:
// com.springanno.dao.UserDao
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
public UserDao(){}
}
// com.springanno.service.UserService
import com.springanno.dao.UserDao;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void printDao() {
System.out.println(userDao);
}
}
// com.springanno.config.MainConfig
import com.springanno.dao.UserDao;
import com.springanno.service.UserService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.springanno")
public class MainConfig {
@Bean("userService2")
public UserService userService(UserDao userDao){
UserService userService = new UserService();
userService.setUserDao(userDao);
return userService;
}
}
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
UserService userService = (UserService) applicationContext.getBean("userService2");
UserDao userDao = applicationContext.getBean(UserDao.class);
userService.printDao();
System.out.println(userDao);
/*
com.springanno.dao.UserDao@21507a04
com.springanno.dao.UserDao@21507a04
*/
@Qualifier
可以通过 @Qualifier
与 @Autowired
搭配使用来指定此次要装配 bean 的 id
。
示例
1、创建测试 Dao:
// com.springanno.dao.UserDao
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
public UserDao(){}
}
2、创建测试 Service:
// com.springanno.service.UserService
import com.springanno.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Qualifier("userDao") // 指定装配 id 为 userDao 的 bean
@Autowired
private UserDao userDao;
public void printDao(){
System.out.println(userDao);
}
}
3、配置包扫描:
// com.springanno.config.MainConfig
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.springanno")
public class MainConfig {
}
4、测试:
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
UserService userService = applicationContext.getBean(UserService.class);
System.out.println(userService);
userService.printDao();
/*
com.springanno.service.UserService@60dcc9fe
com.springanno.dao.UserDao@222114ba
*/
@Primary
@Primary
也是用来对自动装配进行控制的,他用来指定当容器中存在多个类型相同的 bean 时,自动装配优先装配哪个 bean,和 @Bean
一起使用。当然,它不能和 @Qualifier
同时使用。
示例
1、创建测试 Dao:
// com.springanno.dao.UserDao
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
public UserDao(){}
}
2、创建测试 Service:
// com.springanno.service.UserService
import com.springanno.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void printDao(){
System.out.println(userDao);
}
}
3、配置包扫描:
// com.springanno.config.MainConfig
import com.springanno.dao.UserDao;
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("com.springanno")
public class MainConfig {
@Primary // id 为 userDao2 的 bean 优先装配
@Bean
public UserDao userDao2() {
return new UserDao();
}
}
4、测试:
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
UserService userService = applicationContext.getBean(UserService.class);
System.out.println(userService);
userService.printDao();
UserDao userDao = (UserDao) applicationContext.getBean("userDao2");
System.out.println(userDao);
/*
com.springanno.service.UserService@3b2da18f
com.springanno.dao.UserDao@5906ebcb
com.springanno.dao.UserDao@5906ebcb
*/
@Resource
@Resource
注解(JSR250 中定义)相当于 @Autowired
和 @Qualifier
注解一起使用,既能完成自动装配,也能指定要装配 bean 的 id
,不支持 @Primary
注解。
示例
1、创建测试 Dao:
// com.springanno.dao.UserDao
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
public UserDao(){}
}
2、创建测试 Service:
// com.springanno.service.UserService
import com.springanno.dao.UserDao;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class UserService {
@Resource(name = "userDao2")
private UserDao userDao;
public void printDao(){
System.out.println(userDao);
}
}
3、配置包扫描并注册另一个 Dao 到容器:
// com.springanno.config.MainConfig
import com.springanno.dao.UserDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.springanno")
public class MainConfig {
@Bean
public UserDao userDao2() {
return new UserDao();
}
}
4、测试:
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
UserService userService = applicationContext.getBean(UserService.class);
System.out.println(userService);
userService.printDao();
UserDao userDao = (UserDao) applicationContext.getBean("userDao2");
System.out.println(userDao);
/*
com.springanno.service.UserService@2d9d4f9d
com.springanno.dao.UserDao@4034c28c
com.springanno.dao.UserDao@4034c28c
*/
@Inject
@Inject
注解(JSR330 中定义)使用与 @Autowired
注解一致,只是没有属性,作用比较单一。
示例
1、创建测试 Dao:
// com.springanno.dao.UserDao
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
public UserDao(){}
}
2、创建测试 Service:
// com.springanno.service.UserService
import com.springanno.dao.UserDao;
import org.springframework.stereotype.Service;
import javax.inject.Inject;
@Service
public class UserService {
/*
与 Autowired 相同,需导包
<dependency>
<groupId>javax.inject</groupId>
<artifactId>com.springsource.javax.inject</artifactId>
<version>1.0.0</version>
</dependency>
*/
@Inject
private UserDao userDao;
public void printDao() {
System.out.println(userDao);
}
}
3、配置包扫描:
// com.springanno.config.MainConfig
import com.springanno.dao.UserDao;
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("com.springanno")
public class MainConfig {
@Primary
@Bean
public UserDao userDao2() {
return new UserDao();
}
}
4、测试:
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
UserService userService = applicationContext.getBean(UserService.class);
System.out.println(userService);
userService.printDao();
UserDao userDao = (UserDao) applicationContext.getBean("userDao2");
System.out.println(userDao);
/*
com.springanno.service.UserService@2aa5fe93
com.springanno.dao.UserDao@5c1a8622
com.springanno.dao.UserDao@5c1a8622
*/
@Autowired
是 Spring
定义的,而 @Resource
和 @Inject
是 Java 规范中定义的。
实现 Aware 接口
本内容其实不属于 Spring 注解驱动的内容,只是它也涉及了组件注入的知识,就放这里一起说了。
如果我们自定义的组件想要使用 Spring 容器底层的一些组件,例如 ApplicationContext
、BeanFactory
等,可以让自定义组件实现相应的 Aware 接口,Spring 容器启动时会通过接口的回调给我们注入相应的组件。
1、创建测试 Service:
// com.springanno.service.UserService
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
@Service("testUserServer")
public class UserService implements ApplicationContextAware, BeanNameAware, EnvironmentAware {
public void setBeanName(String beanName) {
System.out.println(beanName);
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println(applicationContext.getBean("testUserServer"));
}
public void setEnvironment(Environment environment) {
System.out.println(environment);
}
}
2、配置包扫描:
// com.springanno.config.MainConfig
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.springanno")
public class MainConfig {
}
3、测试:
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
/*
testUserServer
StandardEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[MapPropertySource {name='systemProperties'}, SystemEnvironmentPropertySource {name='systemEnvironment'}]}
com.springanno.service.UserService@3f56875e
*/
下面是 Spring 提供的继承了 Aware
接口的类:
ApplicationEventPublisherAware (org.springframework.context)
NotificationPublisherAware (org.springframework.jmx.export.notification)
MessageSourceAware (org.springframework.context)
BeanFactoryAware (org.springframework.beans.factory)
EnvironmentAware (org.springframework.context)
EmbeddedValueResolverAware (org.springframework.context)
ResourceLoaderAware (org.springframework.context)
ImportAware (org.springframework.context.annotation)
LoadTimeWeaverAware (org.springframework.context.weaving)
BeanNameAware (org.springframework.beans.factory)
BeanClassLoaderAware (org.springframework.beans.factory)
ApplicationContextAware (org.springframework.context)
评论区