从spring-boot的@SpringBootApplication注解来重新了解sring的注解。
我们知道每一个spring-boot的初始是的程序入口都有一个@SpringBootApplication注解。点开@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 {
// 略...
}
可以看到SpringBootApplication注解类中带着@ComponentScan注解,这也是为什么可以spring-boot可以自动装配bean。当我们进一步查看注解的注解的源码时可以在最低处看到@Component注解。
正是因为注解省去了很多配置文件。
下面我们谈谈什么是spring 的模式注解。
何为模式注解
在spring的官方文档上是这样解释的
Stereotype Annotations
A *stereotype annotation* is an annotation that is used to declare the role that a component plays within the application. For example, the @Repository
annotation in the Spring Framework is a marker for any class that fulfills the role or stereotype of a repository (also known as Data Access Object or DAO).
@Component
is a generic stereotype for any Spring-managed component. Any component annotated with@Component
is a candidate for component scanning. Similarly, any component annotated with an annotation that is itself meta-annotated with@Component
is also a candidate for component scanning. For example,@Service
is meta-annotated with@Component
.
Core Spring provides several stereotype annotations out of the box, including but not limited to:
@Component
,@Service
,@Repository
,@Controller
,@RestController
, and@Configuration
.@Repository
,@Service
, etc. are specializations of@Component
.
构造型注释是一种注释,用于声明组件在应用程序中扮演的角色。例如,Spring Framework中的@Repository注释是任何满足存储库角色(也称为数据访问对象或DAO)的类的标记。
模式注解举例
spirng 注解 | 使用说明 | 起始版本 |
---|---|---|
@Repository | 数据仓库注解 | 2.0 |
@Component | 通用组件模式注解 | 2.5 |
@Service | 服务注解模式 | 2.5 |
@Controller | Web控制器模式注解 | 2.5 |
@Configuration | 配置模式注解 | 3.0 |
spring的两种装配方式
- 配置文件扫描
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
<!-- 寻找被@Component 或者其派生的注解标记的类,将其注册为spring Bean -->
<context:component-scan base-package="com.*" annotation-config="true">
</context:component-scan>
</beans>
- @ComponentScan方式
@ComponentScan(basePackages = "com.dsdj.springboot")
public class SpringConfiguration {
}
spring自定义注解的使用
初始项目https://start.spring.io/
自定义repository注解
package com.dsdj.springbootdemo1.annotation;
import org.springframework.stereotype.Repository;
import java.lang.annotation.*;
/**
* @ClassName MyFirstRepository
* @Description 我的自定义注解
* @Author dsdj
* @Date 2018/12/15 下午4:36
* @Version 1.0
**/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repository
public @interface MyFirstRepository {
String value() default "";
}
自定义了MyFirstRepository注解,继承了@Repository注解,即具有了@Repository注解的功能。
测试:
- 定义一个类
package com.dsdj.springbootdemo1.repository;
import com.dsdj.springbootdemo1.annotation.MyFirstRepository;
/**
* @ClassName TestRepository
* @Description TODO
* @Author dsdj
* @Date 2018/12/15 下午4:44
* @Version 1.0
**/
@MyFirstRepository(value = "testRespository")
public class TestRepository {
}
- 入口函数
package com.dsdj.springbootdemo1.bootstrap;
import com.dsdj.springbootdemo1.repository.TestRepository;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;
/**
* @ClassName RepositoryBootstrap
* @Description 仓储的引导类
* @Author dsdj
* @Date 2018/12/15 下午4:46
* @Version 1.0
**/
@ComponentScan(basePackages = "com.dsdj.springbootdemo1.*")
public class RepositoryBootstrap {
public static void main(String[] args) {
// spring boot的启动入口,获取spring的上下文
ConfigurableApplicationContext context = new SpringApplicationBuilder(RepositoryBootstrap.class)
// spring boot2.0写法,说明不是web类型项目
.web(WebApplicationType.NONE)
.run(args);
TestRepository testRespository = context.getBean("testRespository", TestRepository.class);
System.out.println("bean是否扫描到:"+testRespository.toString());
context.close();
}
}
- 输出
2018-12-15 16:58:37.991 INFO 21446 --- [ main] c.d.s.bootstrap.RepositoryBootstrap : No active profile set, falling back to default profiles: default
2018-12-15 16:58:38.219 INFO 21446 --- [ main] c.d.s.bootstrap.RepositoryBootstrap : Started RepositoryBootstrap in 0.521 seconds (JVM running for 0.958)
bean是否扫描到:com.dsdj.springbootdemo1.repository.TestRepository@2f465398
可以看到spring-boot 成功装配了bean
通过上述的例子可以看到注解的特性
注解的特性
- 继承性
@MyFirstRepository注解类中有@Repostory注解,使之可以实现@Repostory的功能,所以spring可以对@MyFirstRepository注解的类进行装配。
同理,当我们继续查看@Repository的源码时,可以看到@Component元注解,也就是说,@ComponentScan对@Component注解类进行装配,而@Repository、@Controller、@Service“继承”了@Component所有可以进行装配。
- 层次性
可以发现@Component–>@Repostory—>@MyFirstRepository一种层次的关系。