springboot的自動(dòng)裝配源于SpringFramework的手動(dòng)裝備,SpringFramework手動(dòng)裝配來看起。
手動(dòng)裝配是按照SpringFramework的版本進(jìn)行管理的,前提差不多都是基于基于注解驅(qū)動(dòng)。
【什么是Spring模式注解】
一種用于聲明在應(yīng)用中扮演“組件”角色的注解
這里的應(yīng)用:在Spring或者SpringBoot應(yīng)用
組件:例如:@Component spring2.5,@Service:服務(wù)類注解 spring2.5,@Configuration 配置注解spring3
github上定義:A stereotype annotation is an annotation that is used to declare the role that a component plays within the application.
github關(guān)于模式注解(Stereotype Annotations)的解釋中最為重要的一點(diǎn)就是:
凡是被 @Component 元標(biāo)注(meta-annotated)的注解,如 @Service ,@Repository等,當(dāng)任何組件標(biāo)注它時(shí),也被視作組件掃描的候選對(duì)象,可以理解為組件 是包括@Component及他的所有“派生”。
常用的模式注解
@Repository 數(shù)據(jù)倉儲(chǔ)模式注解 起始版本2.0
@Component 通用組件模式注解 起始版本 2.5
@Service 服務(wù)模式注解 起始版本2.5
@Controller 控制器模式注解 起始版本2.5
@Configuration 配置類模式注解 起始版本 3.0
【裝配的方式有2種】
1)xml方式:<context:component-scan> spring2.5提出的方案
base-package指明的這個(gè)包下所有的組件都會(huì)被掃描到
<meta charset="utf-8">
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
[http://www.springframework.org/schema/beans/spring-beans.xsd](http://www.springframework.org/schema/beans/spring-beans.xsd)
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-
context.xsd">
<!-- 激活注解驅(qū)動(dòng)特性 -->
<context:annotation-config />
<!-- 找尋被 @Component 或者其派生 Annotation 標(biāo)記的類(Class),將它們注冊(cè)為 Spring Bean -->
<context:component-scan base-package="com.imooc.dive.in.spring.boot" />
</beans>
2)注解方式:@ComponentScan ,是spring3.1的方案
springboot1.0是基于spring4進(jìn)行開發(fā)。
@ComponentScan(basePackages = "com.imooc.dive.in.spring.boot")
public class SpringConfiguration {
...
}
【Spring Framework手動(dòng)裝配自定義模式注解】
自定義模式注解,有兩個(gè)性質(zhì)@Component “派生性”和@Component “層次性”,我們從一個(gè)小栗子來看看這2個(gè)性質(zhì)的體現(xiàn)
【@Component “派生性”】
注意這里的派生不是真正的派生就是一種理解
【栗子】
新建一個(gè)工程,工程下新建一個(gè)包annotation ,這個(gè)包下新建一個(gè)注解類FirstLevelRepository,作為一級(jí)倉儲(chǔ)
/**
* 一級(jí) {@link Repository @Repository}
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repository // 數(shù)據(jù)倉儲(chǔ)模式注解
public @interface FirstLevelRepository {
String value() default "";
}
備注:
@Repository // 數(shù)據(jù)倉儲(chǔ)模式注解
通過源碼可以看到@Repository元標(biāo)注的是@Component,
并且,他們的簽名都保持這一致,屬性方法value()
這就是所謂的“派生性”
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
@AliasFor(
annotation = Component.class
)
String value() default ""; //簽名 一致性 :屬性方法value
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
String value() default "";
}
接下來,我們要將這個(gè)注解作用到一個(gè)類上面
新建一個(gè)包repository,下面新建一個(gè)類MyFirstLevelRepository,類上面添加我們剛才自定義的注解,通過value來添加一個(gè)bean的名稱,注意名字的第一個(gè)字母要小寫,在進(jìn)行組件掃描后MyFirstLevelRepository這個(gè)類就成為一個(gè)bean。
/**
* 我的{@link FirstLevelRepository}
*/
@FirstLevelRepository(value = "myFirstLevelRepository") //Bean的名字
public class MyFirstLevelRepository {
}
我們新建一個(gè)bootstrap包,下面建一個(gè)引導(dǎo)類,就是啟動(dòng)類RepositoryBootstrap,這里我們不使用注解@SpringBootApplication來標(biāo)注引導(dǎo)類,我們采用SpringApplicationBuilder()spring2.0寫法。
可以指定類型web,我們定義為非web類型 ,一個(gè)普通類型,注解驅(qū)動(dòng)
/**
* 倉儲(chǔ)引導(dǎo)類
*/
@ComponentScan(basePackages = "com.cbt.diveinspringboot.repository")
public class RepositoryBootstrap {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(RepositoryBootstrap.class)
.web(WebApplicationType.NONE)
.run(args);
// myFirstLevelRepository Bean是否存在
MyFirstLevelRepository myFirstLevelRepository = context.getBean("myFirstLevelRepository",MyFirstLevelRepository.class);
System.out.println("myFirstLevelRepository Bean:" + myFirstLevelRepository);
context.close();
}
}
說明:
1、run()返回的對(duì)象 ConfigurableApplicationContext
2、關(guān)閉上下文context
3、掃描MyFirstLevelRepository 這個(gè)類的方式:
1)可以包MyFirstLevelRepository這個(gè)bean丟進(jìn)去
2)也可以把RepositoryBootstrap 這個(gè)bean丟進(jìn)去
4、這里先采用注解@ComponentScan 的裝配方式,這個(gè)@FirstLevelRepository組件可以用來識(shí)別我們的MyFirstLevelRepository類。
通過@ComponentScan 掃描包下所有的類,
類被@FirstLevelRepository標(biāo)記的就會(huì)被認(rèn)為是一個(gè)bean,我們可以通過Bean的名稱進(jìn)行獲取。
通過上下文對(duì)象去獲取到bean,第一個(gè)參數(shù)是bean的名稱,就是通過類上的注解value獲取的,第二個(gè)參數(shù)bean的類型,這種方式不用進(jìn)行類型強(qiáng)轉(zhuǎn)的
運(yùn)行引導(dǎo)類:結(jié)果顯示進(jìn)行組件掃描后MyFirstLevelRepository這個(gè)類就成為一個(gè)bean了。

如果你采用@Component注解來替換我們自定義的注解@ FirstLevelRepository結(jié)果是一樣的 ,你可以自己運(yùn)行看看 ----這就是所謂的“派生性”
可以一直注解上去
@Component(value = "myFirstLevelRepository")
public class MyFirstLevelRepository {
}
【@Component “層次性”】就是自定義的注解還可以用來標(biāo)注在其他自定義的注解上面
在annotation包下新建注解SecondLevelRepository
簽名要保持一致
/**
* 二級(jí){@link Repository }
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@FirstLevelRepository //標(biāo)注自定義注解
public @interface SecondLevelRepository {
String value() default "";
}
將這個(gè)@SecondLevelRepository注解添加到MyFirstLevelRepository類
/**
* 我的{@link SecondLevelRepository}
*/
@SecondLevelRepository(value = "myFirstLevelRepository")
public class MyFirstLevelRepository {
}
層次關(guān)系:
- @Component
2.@Repository
3.@FirstLevelRepository
4.@SecondLevelRepository
運(yùn)行引導(dǎo)類:結(jié)果和上面是一樣的。
我們可以再看一個(gè)栗子:
注解:@SpringBootApplication
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
看一下里面的:@SpringBootConfiguration這個(gè)注解,這個(gè)注解標(biāo)注@Configuration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
@Configuration注解又元標(biāo)注了@Component
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
@AliasFor(
annotation = Component.class
)
String value() default "";
}
說明@SpringBootApplication也是屬于模式注解