前言
在平常利用SpringBoot開發的過程當中,咱們開發的Bean大部分都是依賴於spring容器進行管理,這樣很方便平常Bean的注入。
你們都知道對象的建立必須經過構造方法建立,構造方法分爲兩種,一種時無參(此方法只是建立了個空對象,後續使用屬性時還須要set/get),另一種時重載的有參構造器(此方法建立後的對象,對於已經賦值的屬性固然能夠立馬使用),因此Spring在建立Bean的時候也無非就這兩種(默認時無參構造建立),基於spring體系的瘡癰建立Bean註解有:好比@Configuration裏的@Bean,好比@Component,若是是spring mvc的話,還有一些專用的@Controller,@Service,@Repository。java
引入
那麼,使用spring boot時,若是想本身實現一些初始設置比較複雜的bean時,能夠在類上用@Configuration註解,而後類內部在返回具體bean的方法上使用@Bean註解。
那麼,要讓容器找到這個配置類,並讓容器進行管理的話,方法有這麼幾種:spring
方法一:@ComponentScan註解
將配置類放到@ComponentScan註解所指定的package裏。
如下是截取springboot Guide中的一段話:
sql
方法二:使用@Import註解
首先,@Import是spring中的內置註解,因此spring會對此註解進行管理。 這個註解的主要用途截取spring的源碼說明,而後逐一講解:
a.容許使用@Configuration註解的類
這個比較簡單,若是明確知道須要引入哪一個配置類,直接引入就能夠。springboot
b.容許是實現ImportSelector接口的類
若是並不肯定引入哪一個配置類,須要根據@Import註解所標識的類或者另外一個註解(一般是註解)裏的定義信息選擇配置類的話,用這種方式。
比較典型的是註解@EnableTransactionManagementmybatis
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來選擇使用哪一個配置類的。mvc
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,而如何把這些普通的類放入容器,就是經過註解app
典型表明@MapperScanide
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下全部的類,並放入容器中。ui
d.正如源碼中的備註同樣,"as well as regular component",說明,Import能夠像相似於@Component此功能的註解同樣,在容器啓動的時候將此類定義爲一個bean,並將此bean交於容器管理,但此用法較少。