了解SpringBoot的自动装配前,还是要了解下Spring的手动装配,Spring有很多种手动装配模式,今天先介绍模式注解装配
模式注解是一种用于声明在应用中扮演“组件”角色的注解。什么意思呢?这句话有两个关键字,一个是应用,一个是组件,应用其实指的就是我们的Spring应用或者SpringBoot应用,什么是组件呢,其实用过Spring的同学知道那些在类上拥有@Component,@Service,@Repository的注解就是一种组件。
如Spring Framework 中的 @Repository 标注在任何类上 ,用于扮演仓储角色的模式注解;@Component 作为一种由 Spring 容器托管的通用模式组件,任何被@Component 标准的组件均为组件扫描的候选对象。类似地,凡是被 @Component 元标注(meta-annotated)的注解,如 @Service ,当任何组件标注它时,也被视作组件扫描的候选对象。我们可以看看@Service注解的源码:
这个注解其实包含了@Component。所以它也可以被视为组件扫描的候选对象。
差点忘记了Spring3.1中出现的新注解,@Configuration,这表示当前的类是一个配置的注解。下图是模式注解举例:
那么讲了这么多的模式注解,怎么对他们进行装配呢?装配呢一共有两种方式:
一种是<context:component-scan>方式,这种方式往往写在XML配置文件中:
<!-- 激活注解驱动特性 -->
<context:annotation-config />
<!-- 找寻被 @Component 或者其派生 Annotation 标记的类(Class),将它们注册为 Spring Bean -->
<context:component-scan base-package="com.xxx" />
还有一种是@ComponentScan
@ComponentScan(basePackages = "com.xxx")
public class SpringConfiguration {
...
}
OK,模式注解讲到这里,那么我开始自定义一个模式注解,并对它进行手动装配。
首先定义一个注解FirstLevelRepository ,一会儿这个注解会被应用到其他类上,用于被装配,这个注解很简单,就是其上面有一个@Repository,另外属性就只有一个value
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repository
public @interface FirstLevelRepository {
String value() default "";
}
再自定义一个注解,这个注解上面使用了FirstLevelRespository注解:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@FirstLevelRepository
public @interface SecondLevelRepository {
String value() default "";
}
注解定义完了,那么我就要开始定义一个类来使用这些注解了:
@SecondLevelRepository(value = "myFirstLevelRepository") // Bean 名称
public class MyFirstLevelRepository {
}
定义了一个什么都不做的类,这个类上面使用了SecondLevelRepository注解。
接下来我们写一个启动类来对这些模式注解进行装配:
@ComponentScan(basePackages = "com.zzm.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();
}
}
这里我们使用了SpringApplicationBuilder,这是个什么东东呢?官网说它可以替代我们在SpringBoot中经常使用的SpringApplication.run(XXX.class, args),并且能够构建Spring上下文。什么时候用SpringApplicationBuilder呢?当你不想装配太多东西,需求很简单的时候,就比如我们这个例子,只想装配我们自定义的注解部分。这里还写了一个SpringApplicationBuilder(RepositoryBootstrap.class).web(WebApplicationType.NONE),表示我们的应用是非web类型的应用,不要启动内嵌的web server~类上面的@ComponentScan(basePackages = "com.zzm.repository")表示扫描指定包路径下的组件。也就是我们的MyFirstLevelRepository。
启动应用后会发现是这样的:
表示我们的类被装载到容器中了,可以发现@Component似乎具有一种“派生性”的作用。
@Component
@Repository
@FirstLevelRepository
@SecondLevelRepository
其实我们在springBoot中常用的@SpringBootApplication就是一个模式注解。
OK模式注解装配就讲到这里,下一篇文章将讲述别的装配模式