1)、@Autowired:自动注入:
@Autowired:构造器,参数,方法,属性;都是从容器中获取参数组件的值
1)、[标注在方法位置]:@Bean+方法参数;参数从容器中获取;默认不写@Autowired效果是一样的;都能自动装配
2)、[标在构造器上]:如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取
3)、放在参数位置:
使用方法:
1)、默认优先按照类型去容器中找对应的组件:applicationContext.getBean(Test.class);找到就赋值
2)、如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
applicationContext.getBean("test")
3)、@Qualifier("test"):使用@Qualifier指定需要装配的组件的id,而不是使用属性名
4)、自动装配默认一定要将属性赋值好,没有就会报错;
可以使用@Autowired(required=false);
5)、@Primary:让Spring进行自动装配的时候,默认使用首选的bean;
也可以继续使用@Qualifier指定需要装配的bean的名字
如果想了解解析注解的原理可参考:AutowiredAnnotationBeanPostProcessor类
2)、Spring还支持使用@Resource(JSR250)和@Inject(JSR330)[java规范的注解]
@Resource:
可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的;
没有能支持@Primary功能没有支持@Autowired(reqiured=false);
@Inject:
需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能;
3)、@ComponentScan作用就是根据定义的扫描路径,把符合扫描规则的类装配到spring容器中;
该注解比较复杂参数也比较多,因此我会将部分代码贴出;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
@AliasFor("basePackages")
String[] value() default {};
@AliasFor("value")
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
String resourcePattern() default "**/*.class";
boolean useDefaultFilters() default true;
ComponentScan.Filter[] includeFilters() default {};
ComponentScan.Filter[] excludeFilters() default {};
boolean lazyInit() default false;
@Retention(RetentionPolicy.RUNTIME)
@Target({})
public @interface Filter {
FilterType type() default FilterType.ANNOTATION;
@AliasFor("classes")
Class<?>[] value() default {};
@AliasFor("value")
Class<?>[] classes() default {};
String[] pattern() default {};
}
}
basePackages与value: 用于指定包的路径,进行扫描
basePackageClasses: 用于指定某个类的包的路径进行扫描
nameGenerator: bean的名称的生成器
useDefaultFilters: 是否开启对@Component,@Repository,@Service,@Controller的类进行检测
includeFilters: 包含的过滤条件
FilterType.ANNOTATION:按照注解过滤
FilterType.ASSIGNABLE_TYPE:按照给定的类型
FilterType.ASPECTJ:使用ASPECTJ表达式
FilterType.REGEX:正则
FilterType.CUSTOM:自定义规则
4)、 @Conditional:自定义规则是个什么东西呢,它可以根据代码中设置的条件装载不同的bean,比如说当一个接口有两个实现类时,我们要把这个接口交给Spring管理时通常会只选择实现其中一个实现类,这个时候我们总不能使用if-else吧,所以这个@Conditional的注解就出现了;
1)、Spring自己的使用场景:激活不通的环境(spring.profiles.active=dev)可参考@Profile实现方式;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({ProfileCondition.class})
public @interface Profile {
String[] value();
}
class ProfileCondition implements Condition {
ProfileCondition() {
}
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
if (context.getEnvironment() != null) {
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if (attrs != null) {
Iterator var4 = ((List)attrs.get("value")).iterator();
Object value;
do {
if (!var4.hasNext()) {
return false;
}
value = var4.next();
} while(!context.getEnvironment().acceptsProfiles((String[])((String[])value)));
return true;
}
}
return true;
}
}
5)、 @Configuration:用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器;
@Configuration不可以是final类型;
@Configuration不可以是匿名类;
嵌套的configuration必须是静态类。
@Configuation等价于<Beans></Beans>
@Bean等价于<Bean></Bean>
@ComponentScan等价于<context:component-scan base-package=”xxx.xxx.xxx”/>
项目中的使用:
@Configuration
@ConditionalOnClass(Endpoint.class)
@AutoConfigureAfter(EndpointAutoConfiguration.class)
public class RefreshEndpointAutoConfiguration {
@ConditionalOnMissingBean
@ConditionalOnEnabledHealthIndicator("refresh")
@Bean
RefreshScopeHealthIndicator refreshScopeHealthIndicator(RefreshScope scope,
ConfigurationPropertiesRebinder rebinder) {
return new RefreshScopeHealthIndicator(scope, rebinder);
}
@ConditionalOnClass(IntegrationMBeanExporter.class)
protected static class RestartEndpointWithIntegration {
@Autowired(required = false)
private IntegrationMBeanExporter exporter;
@Bean
@ConditionalOnMissingBean
public RestartEndpoint restartEndpoint() {
RestartEndpoint endpoint = new RestartEndpoint();
if (this.exporter != null) {
endpoint.setIntegrationMBeanExporter(this.exporter);
}
return endpoint;
}
}
@ConditionalOnMissingClass("org.springframework.integration.monitor.IntegrationMBeanExporter")
protected static class RestartEndpointWithoutIntegration {
@Bean
@ConditionalOnMissingBean
public RestartEndpoint restartEndpoint() {
return new RestartEndpoint();
}
}
@Bean
@ConfigurationProperties("endpoints.pause")
public RestartEndpoint.PauseEndpoint pauseEndpoint(RestartEndpoint restartEndpoint) {
return restartEndpoint.getPauseEndpoint();
}
@Bean
@ConfigurationProperties("endpoints.resume")
public RestartEndpoint.ResumeEndpoint resumeEndpoint(
RestartEndpoint restartEndpoint) {
return restartEndpoint.getResumeEndpoint();
}
@Configuration
@ConditionalOnProperty(value = "endpoints.refresh.enabled", matchIfMissing = true)
@ConditionalOnBean(PropertySourceBootstrapConfiguration.class)
protected static class RefreshEndpointConfiguration {
@Bean
@ConditionalOnMissingBean
public RefreshEndpoint refreshEndpoint(ContextRefresher contextRefresher) {
RefreshEndpoint endpoint = new RefreshEndpoint(contextRefresher);
return endpoint;
}
}
}