1. @Autowired & @Qualifier & @Primary
1.1 @Autowired
1.1.1 使用方式
@Autowired
:自动注入,如果没有就会报错,可以指定 required=false
避免报错
-
默认优先按照类型去容器中找对应的组件:
applicationContext.getBean(Xxx.class)
,找到就赋值,如果找到多个相同类型的组件,再将属性的名称作为组件的 id 去容器中查找:applicationContext.getBean("xxx")
-
标注在构造器上:如果组件只有一个有参构造器,这个有参构造器的
@Autowired
可以省略,参数位置的组件是从容器中获取的 -
标注在方法位置:
@Autowired
可以使用在 setter 方法上,Spring 容器创建当前对象时会自动调用方法完成赋值,方法使用的自定义类型参数的值从 IOC 容器中获取 -
标注在参数上:
@Bean
注解标注方法中的参数会从容器中获取,此时的@Autowired
可以省略
1.1.2 环境搭建
代码已经上传至 https://github.com/masteryourself-tutorial/tutorial-spring ,详见
tutorial-spring-framework/tutorial-spring-framework-injection/tutorial-spring-framework-injection-autowired
工程
1. PersonController
@Controller
@ToString
public class PersonController {
@Autowired
private PersonService personService2;
}
2. StudentController
@Data
public class StudentController {
private PersonService personService;
/**
* 只要一个有参的构造参数
*
* @param personService
*/
public StudentController(PersonService personService) {
this.personService = personService;
}
}
3. TeacherController
@Controller
@ToString
public class TeacherController {
private PersonService personService;
/*@Autowired*/
public TeacherController(/*@Autowired*/ PersonService personService2) {
this.personService = personService2;
}
}
4. UserController
@Controller
@ToString
public class UserController {
private PersonService personService;
@Autowired
public void setPersonService(PersonService personService1) {
this.personService = personService1;
}
}
5. SpringConfig
@Configuration
@ComponentScan("pers.masteryourself.tutorial.spring.framework.injection")
public class SpringConfig {
@Bean
public PersonService personService1() {
return new PersonService("1");
}
@Bean
public PersonService personService2() {
return new PersonService("2");
}
@Bean
public StudentController studentController(/*@Autowired*/ PersonService personService1){
return new StudentController(personService1);
}
}
6. AutowiredApplication
public class AutowiredApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
PersonController personController = context.getBean(PersonController.class);
// PersonController(personService2=PersonService(label=2))
System.out.println(personController);
UserController userController = context.getBean(UserController.class);
// UserController(personService=PersonService(label=1))
System.out.println(userController);
TeacherController teacherController = context.getBean(TeacherController.class);
// TeacherController(personService=PersonService(label=2))
System.out.println(teacherController);
StudentController studentController = context.getBean(StudentController.class);
// StudentController(personService=PersonService(label=1))
System.out.println(studentController);
}
}
1.2 @Qualifier
1.2.1 使用方式
使用 @Qualifier
指定需要装配的组件的 id,而不是使用属性名
1.2.2 环境搭建
代码已经上传至 https://github.com/masteryourself-tutorial/tutorial-spring ,详见
tutorial-spring-framework/tutorial-spring-framework-injection/tutorial-spring-framework-injection-qualifier
工程
1. PersonController
@ToString
@Component
public class PersonController {
@Autowired
@Qualifier("personService1")
private PersonService personService2;
}
1.3 @Primary
1.3.1 使用方式
让 Spring 进行自动装配的时候,默认使用首选的 bean;也可以强制使用 @Qualifier
明确指定需要装配的 bean 的名字
1.3.2 环境搭建
代码已经上传至 https://github.com/masteryourself-tutorial/tutorial-spring ,详见
tutorial-spring-framework/tutorial-spring-framework-injection/tutorial-spring-framework-injection-primary
工程
1. SpringConfig
@Configuration
@ComponentScan("pers.masteryourself.tutorial.spring.framework.injection")
public class SpringConfig {
@Bean
@Primary
public PersonService personService1() {
return new PersonService("1");
}
@Bean
public PersonService personService2() {
return new PersonService("2");
}
}
2. @Resource & @Inject
2.1 @Resource
@Resource
是 java 规范定义的注解,可以和 @Autowired
一样实现自动装配功能,默认是按照组件名称进行装配的
不支持 @Primary
功能,不支持 @Autowired(reqiured=false)
2.2 @Inject
需要导入 javax.inject
的包,和 Autowired 的功能一样,但没有 required=false
的功能
3. Aware
3.1 使用方式
自定义组件实现 xxxAware;在创建对象的时候,会调用接口规定的方法注入相关组件
3.2 环境搭建
代码已经上传至 https://github.com/masteryourself-tutorial/tutorial-spring ,详见
tutorial-spring-framework/tutorial-spring-framework-injection/tutorial-spring-framework-injection-aware
工程
1. MyAware
@Component
public class MyAware implements ApplicationEventPublisherAware, BeanFactoryAware, EnvironmentAware,
EmbeddedValueResolverAware, BeanNameAware, ApplicationContextAware, ImportAware {
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println(String.format("{%s} ==========================>>>>>>>>>>>>>>>>>>>>>>>>>>>", "setBeanFactory"));
System.out.println(beanFactory.getBean("myAware"));
}
@Override
public void setBeanName(String beanName) {
System.out.println(String.format("{%s} ==========================>>>>>>>>>>>>>>>>>>>>>>>>>>>", "setBeanName"));
System.out.println("beanName is:" + beanName);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println(String.format("{%s} ==========================>>>>>>>>>>>>>>>>>>>>>>>>>>>", "setApplicationContext"));
System.out.println("applicationContext 是否属于 AnnotationConfigApplicationContext:" +
(applicationContext instanceof AnnotationConfigApplicationContext));
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
System.out.println(String.format("{%s} ==========================>>>>>>>>>>>>>>>>>>>>>>>>>>>", "setApplicationEventPublisher"));
System.out.println("applicationEventPublisher is:" + applicationEventPublisher);
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
System.out.println(String.format("{%s} ==========================>>>>>>>>>>>>>>>>>>>>>>>>>>>", "setEmbeddedValueResolver"));
System.out.println(resolver.resolveStringValue("my os is [${os.name}]"));
}
@Override
public void setEnvironment(Environment environment) {
System.out.println(String.format("{%s} ==========================>>>>>>>>>>>>>>>>>>>>>>>>>>>", "setEnvironment"));
System.out.println("当前 encoding:" + environment.getProperty("file.encoding"));
}
@Override
public void setImportMetadata(AnnotationMetadata annotationMetadata) {
System.out.println(String.format("{%s} ==========================>>>>>>>>>>>>>>>>>>>>>>>>>>>", "setImportMetadata"));
Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(Import.class.getName());
System.out.println("获取注解信息:" + attributes);
}
}
4. @Profile
4.1 使用方式
@Profile
:指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件
加了环境标识的 bean,只有这个环境被激活的时候才能注册到容器中。默认是 default 环境
写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效
没有标注环境标识的 bean 在任何环境下都是加载的
4.2 环境搭建
代码已经上传至 https://github.com/masteryourself-tutorial/tutorial-spring ,详见
tutorial-spring-framework/tutorial-spring-framework-injection/tutorial-spring-framework-injection-profile
工程
1. SpringConfig
@Configuration
public class SpringConfig {
@Profile("default")
@Bean
public Datasource localDatasource(){
return new Datasource("local");
}
@Profile("dev")
@Bean
public Datasource devDatasource(){
return new Datasource("dev");
}
@Profile("test")
@Bean
public Datasource testDatasource(){
return new Datasource("test");
}
@Profile("prod")
@Bean
public Datasource prodDatasource(){
return new Datasource("prod");
}
}
4.3 激活
1. 通过启动参数激活
通过在 VM options
中配置启动参数 -Dspring.profiles.active=dev,test
2. 通过代码激活
public static void main(String[] args) {
// 1. 创建一个 AnnotationConfigApplicationContext
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 2. 设置需要激活的环境
context.getEnvironment().setActiveProfiles("dev", "test");
// 3. 注册主配置类
context.register(SpringConfig.class);
// 4. 刷新容器
context.refresh();
String[] names = context.getBeanNamesForType(Datasource.class);
for (String name : names) {
// devDatasource
// testDatasource
System.out.println(name);
}
}