ImportSelector,ImportBeanDefinitionRegistrar,@Import实现自定义注解

@Import

官方解释:

1
2
3
4
5
Indicates one or more @Configuration classes to import.
Provides functionality equivalent to the <import/> element in Spring XML. Allows for importing @Configuration classes, ImportSelector and ImportBeanDefinitionRegistrar implementations, as well as regular component classes (as of 4.2; analogous to AnnotationConfigApplicationContext.register).
@Bean definitions declared in imported @Configuration classes should be accessed by using @Autowired injection. Either the bean itself can be autowired, or the configuration class instance declaring the bean can be autowired. The latter approach allows for explicit, IDE-friendly navigation between @Configuration class methods.
May be declared at the class level or as a meta-annotation.
If XML or other non-@Configuration bean definition resources need to be imported, use the @ImportResource annotation instead.

翻译:

1
2
3
4
5
表示要导入的一个或多个@Configuration类。
提供与Spring XML中的<import />元素等效的功能。 允许导入@Configuration类,ImportSelector和ImportBeanDefinitionRegistrar实现,以及常规组件类(从4.2开始;类似于AnnotationConfigApplicationContext.register)。
应该使用@Autowired注入来访问在导入的@Configuration类中声明的@Bean定义。 bean本身可以自动装配,或者声明bean的配置类实例可以自动装配。 后一种方法允许在@Configuration类方法之间进行显式的,IDE友好的导航。
可以在类级别声明或作为元注释声明。
如果需要导入XML或其他非@Configuration bean定义资源,请改用@ImportResource注释。

有个很重要的说明是: 允许导入@Configuration类,ImportSelector和ImportBeanDefinitionRegistrar实现,以及常规组件类

ImportSelector

是一个接口,实现方法用于返回需要导入的组件的全类名数组,返回结果会被注入容器。spring的事务实现选择org.springframework.transaction.annotation.TransactionManagementConfigurationSelector,dubbo的数据绑定选择org.apache.dubbo.config.spring.context.annotation.DubboConfigConfigurationSelector

ImportBeanDefinitionRegistrar

是一个接口,自定义bean注册到容器

一般基于这3个来实现自定义注解的实现,Spring很多功能都是用了这3个,如@EnableXXXX注解。

案例

1
2
3
4
5
6
7
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EnableClearSelect.class)
public @interface EnableClear {
boolean custom() default false;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class EnableClearSelect implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
AnnotationAttributes attributes = AnnotationAttributes.fromMap(
importingClassMetadata.getAnnotationAttributes(EnableClear.class.getName()));
boolean custom = attributes.getBoolean("custom");
if(custom){
return new String[]{Clear1.class.getName()};
}else {
return new String[]{Clear2.class.getName()};
}
}
}
1
2
3
4
5
6
public class Clear1 {
@PostConstruct
public void init(){
System.out.println("Clear1");
}
}

如何使自定义注解生效?

法1

1
2
3
4
5
@Configuration
@EnableClear(custom=true)
public class MyClearConfig {

}

注意点:自定义注解必须被@Configuration@Component注解,即MyClearConfig必须是一个bean,自定义注解才会生效

法2

1
2
3
4
@EnableClear(custom=true) 
public class MyClearConfig {

}
1
2
3
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(MyClearConfig .class);
applicationContext.refresh();

法2手动将MyClearConfig注入到容器,一般用于写测试用例,正常情况下推荐用法1。

注意:如果Clear1被其他Spring或者基于Spring自定义注解所注解,那么这些注解也会起生效,只要加入容器,就会起作用,具有连带作用

1
2
3
4
5
6
7
8
9
10
11
@EnableScheduling
public class Clear1 {
@PostConstruct
public void init(){
System.out.println("Clear1");
}

@Scheduled(fixedRate = 1000)
public void scheduling(){
System.out.println("scheduling");
}

会不断的打印scheduling


学习这个主要是为了学习dubbo数据绑定以及dubbo自定义注解的实现。