5
前言

在日常利用SpringBoot开发的过程中,我们开发的Bean大部分都是依赖于spring容器进行管理,这样很方便日常Bean的注入。
大家都知道对象的创建必须通过构造方法创建,构造方法分为两种,一种时无参(此方法只是创建了个空对象,后续使用属性时还需要set/get),另外一种时重载的有参构造器(此方法创建后的对象,对于已经赋值的属性当然可以立马使用),所以Spring在创建Bean的时候也无非就这两种(默认时无参构造创建),基于spring体系的疮痈创建Bean注解有:比如@Configuration里的@Bean,比如@Component,如果是spring mvc的话,还有一些专用的@Controller,@Service,@Repository。

引入

那么,使用spring boot时,如果想自己实现一些初始设置比较复杂的bean时,可以在类上用@Configuration注解,然后类内部在返回具体bean的方法上使用@Bean注解。
那么,要让容器找到这个配置类,并让容器进行管理的话,方法有这么几种:

方法一:@ComponentScan注解

将配置类放到@ComponentScan注解所指定的package里。
以下是截取springboot Guide中的一段话:
clipboard.png

方法二:使用@Import注解
首先,@Import是spring中的内置注解,所以spring会对此注解进行管理。
这个注解的主要用途截取spring的源码说明,然后逐一讲解:

clipboard.png

a.允许使用@Configuration注解的类

这个比较简单,如果明确知道需要引入哪个配置类,直接引入就可以。

b.允许是实现ImportSelector接口的类

如果并不确定引入哪个配置类,需要根据@Import注解所标识的类或者另一个注解(通常是注解)里的定义信息选择配置类的话,用这种方式。
比较典型的是注解@EnableTransactionManagement

java代码:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({TransactionManagementConfigurationSelector.class})
public @interface EnableTransactionManagement {
    boolean proxyTargetClass() default false;
    AdviceMode mode() default AdviceMode.PROXY;
    int order() default 2147483647;
}
 

是通过TransactionManagementConfigurationSelector类,根据注解@EnableTransactionManagement所指定的AdviceMode来选择使用哪个配置类的。

 java代码:   
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

    @Override
    protected String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) {
            case PROXY:
                return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
            case ASPECTJ:
                return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
            default:
                return null;
        }
    }
}
c.允许是实现了ImportBeanDefinitionRegistrar接口的类

一般只要用户确切的知道哪些bean需要放入容器的话,自己便可以通过spring boot里所提供的注解来标识了,比如@Configuration里的@Bean,比如@Component,如果是spring mvc的话,还有一些专用的@Controller,@Service,@Repository。
但是,如果是第三方包,而且又不是确定的类,并且这些类并不是spring专用,所以不想用spring的注解进行侵入式标识,那么如果找到这些类放到spring的容器呢?
这时候就用到了用注解@Import引入ImportBeanDefinitionRegistrar子类的方式,最典型的应用就是mybatis,使用工具自动生成了一批mapper和entity,而如何把这些普通的类放入容器,就是通过注解

典型代表@MapperScan

java代码:

@Retention(RetentionPolicy.RUNTIME)  

@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class)
public @interface MapperScan {
String[] value() default {};
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
Class<? extends Annotation> annotationClass() default Annotation.class;
Class<?> markerInterface() default Class.class;
String sqlSessionTemplateRef() default "";
String sqlSessionFactoryRef() default "";
Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class;
}

这个注解用@Import引入了MapperScannerRegistrar类,这个类里会取得注解@MapperScan作设置的package,然后扫描这个package下所有的类,并放入容器中。

d.正如源码中的备注一样,"as well as regular component",说明,Import可以像类似于@Component此功能的注解一样,在容器启动的时候将此类定义为一个bean,并将此bean交于容器管理,但此用法较少。

Belep
21 声望0 粉丝