前言
Spring Boot 的自动装配看似复杂,其实归根到底就是对Spring 的手动装载进行进一步的封装。熟悉Spring的手动装载SpringBoot的自动装配就自然明了了。
@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 {
以上代码为SpringBoot 启动类上最为常见的@SpringBootApplication注释,在看完本文章后相信读者就能够看明白以上各个注释的含义以及原理。
正文
一、Spring Framework 手工装配
1.模式注解装配
一种用于声明在应用中扮演“组件”角色的注解。如 Spring Framework 中的 @Repository 标注在任何类上 ,用 于扮演仓储角色的模式注解。@Component 作为一种由 Spring 容器托管的通用模式组件,任何被 @Component 标准的组件均为组件扫描的候选对象。类似地凡是被@Component 元标注(meta-annotated)的注解,如 @Service,当任何组件标注它时,也被视作组件扫 描的候选对象。
装配方式:<context:component-scan>
<?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/context http://www.springframework.org/schema/context/springcontext.xsd">
<!-- 激活注解驱动特性 -->
<context:annotation-config />
<!-- 找寻被 @Component 或者其派生 Annotation 标记的类(Class),将它们注册为 Spring Bean -->
<context:component-scan base-package="com.feng.technology" />
</beans>
该方法是用与Spring Framework 中根据指定的包名,扫描被模式注解所修饰的类,放入到ioc容器中和根据bean 中的依赖关系进行自动装配
@ComponentScan
@ComponentScan(basePackages = "com.feng.technology")
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
此方法作用与一致。
1.2自定义注解
Spring 中的注解具有“派生性”,如新增一个注解A,A注解中集成了@Component 注解,那么被注解A所修饰的类都能进行自动装配。例如Spring中的@Repository @Service 等都是通过@Component派生出的。注意:派生的注解必须要跟@Component一样具有 String value 的属性。
如:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface FristAnnotation {
String value() default "";
}
下面我们进行测试,用@FristAnnotation 来进行修饰一个类
@FristAnnotation
public class OneBen {
public void test(){
System.out.println("加载成功!!");
}
}
配置启动类,只扫描OneBean 所在的包
@ComponentScan(basePackages = "com.feng.technology.autofing.bean")
public class AnnontaionBootStrap {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(AnnontaionBootStrap.class)
.web(WebApplicationType.NONE)
.run(args);
OneBean one = context.getBean("oneBean",OneBean.class);
one.test();
context.close();
}
}
运行,测试通过!
1.3注解的层次性
Spring的注解具有层次性,在Spring中被大量的运用,如:@SpringBootConfiguration。@SpringBootConfiguration 中集成了@Configuration,@Configuration集成了@Component。具体请自行查看源码。
我们来实验一下:创建一个新的@SecondAnnotation 里面集成@FristAnnotaion ,并用新建一个twoBean 来进行修饰
@Compent -》 @FristAnnotaion -》 @SecondAnnotation 。所以当被@SecondAnnotation所修饰的twoBean 类也能被 @ComponentScan的扫描识别到。在层次性的特性。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@FristAnnotation
public @interface SecondAnnotation {
String value() default "";
}
@SecondAnnotation(value = "twoBean")
public class TwoBean {
public void test(){
System.out.println("two装配成功");
}
}
修改启动类,并进行测试
@ComponentScan(basePackages = "com.feng.technology.autofing.bean")
public class AnnontaionBootStrap {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(AnnontaionBootStrap.class)
.web(WebApplicationType.NONE)
.run(args);
TwoBean two = context.getBean("twoBean", TwoBean.class);
two.test();
context.close();
}
}
测试通过。