@Import注解源码解析
Spring 3.0之前,创建Bean可以通过xml配置文件与扫描特定包下面的类来将类注入到Spring IOC容器内。而在Spring 3.0之后提供了JavaConfig的方式,也就是将IOC容器里Bean的元信息以java代码的方式进行描述。我们可以通过@Configuration与@Bean这两个注解配合使用来将原来配置在xml文件里的bean通过java代码的方式进行描述
@Import注解提供了@Bean注解的功能,同时还有xml配置文件里标签组织多个分散的xml文件的功能,当然在这里是组织多个分散的@Configuration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
* or regular component classes to import.
*/
Class<?>[] value();
}
从源码里可以看出@Import可以配合 Configuration ,ImportSelector, ImportBeanDefinitionRegistrar 来使用,下面的or表示也可以把Import当成普通的Bean使用
@Import只允许放到类上面,不能放到方法上。下面我们来看具体的使用方式
普通使用方法
这种方式可以直接把类加入到Spring IOC容器
@Configuration
@Import(value={
UserServiceImpl.class})
public class Config {
}
但是这种方式有一些问题,那就是只能使用类的无参构造方法来创建bean,对于有参数的构造方法就无能为力了
结合ImportBeanDefinitionRegistrar接口
ImportBeanDefinitionRegistrar接口的源码如下:
public interface ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}
可以看到这个接口唯一的方法是有两个参数的
-
AnnotationMetadata:通过这个参数可以拿到类的元数据信息
-
BeanDefinitionRegistry:通过这个参数可以操作IOC容器
我们可以使用一个类来实现这个接口
public class UserServiceBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry) {
BeanDefinitionBuilder userService = BeanDefinitionBuilder.rootBeanDefinition(UserServiceImpl.class);
registry.registerBeanDefinition("userService", userService.getBeanDefinition());
}
}
可以看到我们在这个方法里面做一些特殊操作什么的都是可以的,相比较于普通的方式可是灵活了很多
接着我们在@Import注解引入的地方只需要修改为引入UserServiceBeanDefinitionRegistrar就可以了
@Configuration
@Import(value={
UserServiceBeanDefinitionRegistrar.class})
public class Config {
}
结合ImportSelector接口
相比较与实现ImportBeanDefinitionRegistrar接口之后直接操作Bean容器来说,使用ImportSelector会更加优雅一些,只需要返回需要注入类的全限定名就可以了
ImportSelector接口的源码如下:
public interface ImportSelector {
String[] selectImports(AnnotationMetadata importingClassMetadata);
}
public class UserServiceImportSelect implements ImportSelector{
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{
UserServiceImpl.class.getName()};
}