Spring注解驱动开发系列:
自动装配
@Autowired
标注在属性、构造器、方法、参数、注解上,自动从容器中寻找相同类型的bean赋值,如果有多个相同类型的,则根据bean的id来匹配。
默认是需要完成装配的,否则报错,当然也可以设置为非必须:@Autowired(required = false)
- 标注在方法上,最常见的就是配置类中结合@Bean和标在set方法上
@Bean
// factory从容器中获取,可以省略@Autowired
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
......
}
标在set方法上时,创建bean后属性初始化过程会调用set方法
- 标注在构造器上
当类中只有一个构造器时,@Autowired可以省略
-
标注在属性上
-
标注在注解上,相当于合成注解吧
@Primary
当自动装配,容器中又有多个相同类型的bean,我们想要每次都优先使用某个bean时,可以在那个组件上加上@Primary注解。这样容器就会优先使用这个组件实现自动装配
@Qualifier
如果需要指定需要装配bean的id,则可以@Autowired与@Qualifier配合使用
例如:
@Autowired(required = false)
@Qualifier("userDao2")
private UserDao userDaoImpl;
可以将userDao2的bean注入属性中
当这些注解同时出现时,会优先寻找@Qualifier指定的组件,找不到就报错。
@Resource
是JSR250的,不属于Spring
也能实现自动装配功能,可以指定bean的id(这里相当于@Qualifier的功能),不能指定required,但是有更多别的属性(区别于@Autowired)
默认是优先按照属性名称当作bean的id来装配组件,
找不到时会去寻找同类型的bean,
如果刚好有一个,则装配,
如果没有,则报错
如果有多个,且没有@Primary标注的优先的bean,则报错
如果有多个,但是有@Primary标注的优先的bean,则将其注入
@Inject
也能实现自动装配,但是需要导入依赖
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
是JSR330规范,不属于Spring
和@Autowired一样,先类型再属性id,但是,没有required属性,@Autowired算是@Inject的增强版
Aware接口
当我们想要装配Spring底层的一些Bean时,我们应该实现Aware的对应的子接口
示例:
@Component
public class TestAware implements ApplicationContextAware, EmbeddedValueResolverAware {
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println(">>>>>>>>ApplicationContextAware获得》》》"+applicationContext);
}
public void setEmbeddedValueResolver(StringValueResolver resolver) {
System.out.println(">>>>>>>>EmbeddedValueResolverAware获得》》》"+resolver);
String resolveStringValue = resolver.resolveStringValue("配置文件获取值:${people.name},计算SpEL:#{1+1}");
System.out.println(resolveStringValue);
}
}
源码截取分析:
在ApplicationContextAwareProcessor中有一个方法完成一部分Aware的注入,在其中就调用了我们自定义Aware子接口实现类的setXxx方法
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
@Profile
标注在(配置)类或者其方法上,让其只有在某个环境中才会生效
例如:@Profile(“test”)标注在注入组件的方法上时,只有当环境为test才会注入容器
注:环境默认为default,@Profile(“default”)在没有指定环境时,会生效
设置环境的方法:
- 在虚拟机参数位置设置为:-Dspring.profiles.active=test
- 在容器注册启动类前,设置环境变量
// 使用无参构造,避免Spring替我们注册,刷新
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 设置环境变量
context.getEnvironment().setActiveProfiles("test");
// 完成注册、刷新工作
context.register(SpringConfig.class);
context.refresh();