Spring2.5为我们引入了组件自动扫描机制(Annotation),它可以在类路径下寻找标记了@Component、@Service、@Controller、@Repository注解的类,并把这些类纳入到spring容器中管理,它的作用和在xml中使用bean节点配置组件一样。
1,@SpringBootApplication
通常用在主类上,是@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三个注解的复合注解。
注解 | 场景说明 | 备注 |
---|---|---|
@SpringBootConfiguration | 配置类注解,相当于等同于@Configuration | |
@EnableAutoConfiguration | 开启自动配置类,激活spring的自动装配机制 | |
@ComponentScan | 激活@Component扫描 | 通过basePackages可指定扫描路径,默认从声明@ComponentScan所在类的package进行扫描 |
@Configuration(“name”) | 声明当前类为配置类;通过@Resource(name = "restTemplateHttps") 引入不同的类 | name可缺省 |
@Bean | 注解在方法上,声明当前方法的返回值为一个bean,替代xml中的方式; | Spring只调用一次产生这个Bean对象的方法,随后Spring将这个Bean对象放在自己的IOC容器中进行管理。这些bean并不一定要在@Configuration注解下进行创建,在@Component注解下也一样可以。 |
@Order | IOC容器中Bean的执行顺序的优先级; 默认是最低优先级,值越小优先级越高 | Bean的加载顺序不受@Order或Ordered接口的影响; 主要用于相互依赖的对象的执行 |
@EnableConfigurationProperties | 开启对@ConfigurationProperties注解配置Bean的支持; | |
@EnableJpaRepositories | 开启对SpringData JPA Repository的支持; |
2)@EnableAutoConfiguration原理
@Import+@Configuration+Spring SPI
Spring SPI(Service Provider Interface):JDK1.6
是Java提供的一套用来被第三方实现或者扩展的接口,它可以用来启用框架扩展和替换组件。
SPI是调用方来制定接口规范,提供给外部来实现,调用方在调用时则选择自己需要的外部实现。
@EnableAutoConfiguration是一个复合注解:
@AutoConfigurationPackage
:注册扫描路径。
即:@Import(AutoConfigurationPackages.Registrar.class)
,Registrar重写了ImportBeanDefinitionRegistrar,在启动时扫描主启动类包和子包下的所有组件并加载到 Spring 容器。@Import(AutoConfigurationImportSelector.class)
:实现自动装配。
AutoConfigurationImportSelector中的方法public String[] selectImports(AnnotationMetadata annotationMetadata)
,返回类的全路径并加载到IOC容器中,spring再将全路径通过反射(SpringFactoriesLoader.loadFactoryNames
)作为bean放入IOC容器中。
==>举例:mybatis的引用:mybatis将@Configuration和@Bean的全限定名放入META-INF/spring.factories的jar包(存放了所有bean的全路径,以key-value形式存储)。项目引入mybatis依赖后,从spring.factories扫描类的全路径,通过反射将所有的bean放入IOC容器。
2,依赖注入相关注解
3,Spring MVC Annotation
4,参数校验
5,JSON相关注解
6,切面(AOP)注解
7,@Value
(1)支持如下方式的注入:
- 注入普通字符
- 注入操作系统属性
- 注入表达式结果
- 注入其它bean属性
- 注入文件资源
- 注入网站资源
- 注入配置文件
(2)@Value三种情况的用法。
${}
是去找外部配置的参数,将值赋过来
${}
可以出现在java类配置或XML文件中,Spring会从各种已经配置了的来源中解析属性。
要添加属性来源,可以在@Configuration类上增加@PropertySource注解,如:
@Configuration
@PropertySource("classpath:/META-INF/resources/app.properties")
public class Config{……}
- #{}是SpEL表达式,去寻找对应变量的内容
- #{}直接写字符串就是将字符串的值注入进去
8,环境切换
注解 | 场景说明 | 备注 |
---|---|---|
@Profile | 指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件。 | |
@Conditional | 通过实现Condition接口,并重写matches方法,从而决定该bean是否被实例化。 |
9,任务执行&调度:@Async和@Scheduled
11,测试相关注解
12,lombok相关注解
13,缓存相关
Spring 从 3.1 开始就引入了对 Cache 的支持。定义了 org.springframework.cache.Cache 和 org.springframework.cache.CacheManager 接口来统一不同的缓存技术。并支持使用 JCache(JSR-107)注解简化我们的开发。
注解 | 说明 | 备注 |
---|---|---|
@EnableCaching | 开启注解式的缓存支持; | 用于主启动类 |
@Cacheable | 将运行结果缓存,以后查询相同的数据,直接从缓存中取,不需要调用方法。 | 作用于方法 |
@Cacheable常用属性:
属性 | 说明 | 备注 |
---|---|---|
acheNames/value | 用来指定缓存组件的名字 | |
key | 缓存数据时使用的 key,可以用它来指定。默认是使用方法参数的值。(这个 key 你可以使用 spEL 表达式来编写) | |
keyGenerator | key 的生成器。 key 和 keyGenerator 二选一使用 | |
cacheManager | 可以用来指定缓存管理器。从哪个缓存管理器里面获取缓存。 | |
condition | 可以用来指定符合条件的情况下才缓存 | |
unless | 否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存。当然你也可以获取到结果进行判断。(通过 #result 获取方法结果) | unless = "#result.getData() == null" 表示null不缓存 |
sync | 是否使用异步模式。 |
14,java注解(Java标注、元数据)
jdk5引入,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。
注解 | 说明 | 作用域 |
---|---|---|
@Override | 表示重写,如果无法重写会编译报错 | 注解后编译器就进行检查 |
@SuppressWarnings | 选择性地取消特定代码段(即,类或方法)中的警告。 | 注解后编译器就进行检查 |
@Deprecated | 用来注解类、接口、成员方法和成员变量等,用于表示某个元素(类、方法等)已过时。当其他程序使用已过时的元素时,编译器将会给出警告。 | 注解后编译器就进行检查 |
@FunctionalInterface | 指示被修饰的接口是函数式接口,在 JDK8 引入 |
1)@SuppressWarnings
Suppress 抑制;镇压;废止 Warnings警告
@SuppressWarnings(“resource”)是J2SE 提供的一个批注。该批注的作用是给编译器一条指令,告诉它对被批注的代码元素内部的某些警告保持静默。
@SuppressWarnings 批注允许您选择性地取消特定代码段(即,类或方法)中的警告。其中的想法是当您看到警告时,您将调查它,如果您确定它不是问题,您就可以添加一个 @SuppressWarnings 批注,以使您不会再看到警告。
虽然它听起来似乎会屏蔽潜在的错误,但实际上它将提高代码安全性,因为它将防止您对警告无动于衷 — 您看到的每一个警告都将值得注意。
常见参数说明:
参数 | 作用 |
---|---|
deprecation | 使用了不赞成使用的类或方法时的警告 |
unchecked | 执行了未检查的转换时的警告,例如: 当使用集合时没有用泛型来指定集合保存的类型。 |
fallthrough | 当switch程序块直接通往下一种情况没有break时警告; |
path | 再类路径、源文件路径等种有不存在的路径时的警告 |
serial | 当再可序列号的类上缺少serialVerisonUID定义时的警告 |
finally | 任何finally子句不能正常完成时的警告 |
all | 所有的警告 |
2)函数式接口(Functional Interface)
函数式接口就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
@FunctionalInterface
public interface UserService {
void getUser(Long userId);
// 默认方法,可以用多个默认方法
public default void setUser() {
}
// 静态方法
public static void saveUser() {
}
// 覆盖Object中的equals方法
public boolean equals(Object obj);
}
15,数据库相关注解
注解 | 说明 | 作用域 |
---|---|---|
@schema | 标注在class上,表示此类对应的数据库表对应的schema。 |
1)@Schema
可以用如下语句判断某个实体类上是否带有@schema注解,从而得到schema。
bean.getClass().isAnnotationPresent(Schema.class)
16,执行顺序相关的注解
从Java EE5规范开始,Servlet中增加了两个影响Servlet生命周期的注解,@PostConstruct和@PreDestroy,这两个注解被用来修饰一个非静态的void()方法。
1)@PostConstruct
注解后方法执行时间:在依赖注入完成后被自动调用。
服务器加载serlvet >> Constructor >> @Autowired >> @PostConstruct
@PostConstruct
public void someMethod(){}
1>场景
可作为一些数据的常规化加载,比如数据字典之类的。
或者打印一些启动时加载的配置的log。
2)@PreDestroy
执行顺序:destroy >>@PreDestroy>>服务器卸载serlvet
17,处理异常
注解 | 说明 |
---|---|
@ControllerAdvice | 包含@Component,可以被扫描,用于统一处理异常 |
@ExceptionHandler(Exception.class) | 用于方法上表示遇到这个异常就执行这个方法,与@ControllerAdvice 配合使用 |
18,Java Doc
sun公司提供的一个源代码配套的API注解文档。
常用标签 | 说明 | 标签作用域 |
---|---|---|
@author 作者 | 作者标识 | 包、 类、接口 |
@version 版本号 | 版本号 | 包、 类、接口 |
@param 参数名 描述 | 方法的入参名及描述信息 | 方法 |
@return 描述 | 函数返回值 | 方法 |
@deprecated 过期文本 | 标识随着程序版本的提升,当前API已经过期,仅为了保证兼容性依然存在,以此告之开发者不应再用这个API。 | 包、类、接口、值域、构造函数、 方法 |
@throws异常类名 | 构造函数或方法所会抛出的异常 | 方法 |
@exception 异常类名 | 同@throws。 | |
@see #[method或field] | 查看相关内容,如类、方法、变量等。 | 包、类、接口、值域、构造函数、 方法 |
@since 描述文本 | API在什么程序的什么版本后开发支持。 | 包、类、接口、值域、构造函数、 方法 |
{@link #[method或field]} | 链接到某个特定的成员对应的文档中 | 包、类、接口、值域、构造函数、 方法 |
{@value} | 当对常量进行注释时,如果想将其值包含在文档中,则通过该标签来引用常量的值。 | 静态值域 |
19,自定义注解
1)概念
注解可以看作是一种特殊的标记,可以用在方法、类、参数和包上,程序在编译或者运行时可以检测到这些标记而进行一些特殊的处理,例如标注在方法上可以实现接口权限的校验。
2)场景
自定义注解+拦截器或者 AOP。
3)语法(元注解)
元注解:定义其他注解的注解。
//通过关键字 @interface 声明为注解
public @interface SystemConfig {
}
注解的元素类型主要有@Target,@Retention,@Document,@Inherited 用来修饰注解。
1>@Target
表明该注解可以应用的java元素类型。
Target类型 | 描述 |
---|---|
ElementType.TYPE | 应用于类、接口(包括注解类型)、枚举 |
ElementType.FIELD | 应用于属性(包括枚举中的常量) |
ElementType.METHOD | 应用于方法 |
ElementType.PARAMETER | 应用于方法的形参 |
ElementType.CONSTRUCTOR | 应用于构造函数 |
ElementType.LOCAL_VARIABLE | 应用于局部变量 |
ElementType.ANNOTATION_TYPE | 应用于注解类型 |
ElementType.PACKAGE | 应用于包 |
ElementType.TYPE_PARAMETER | 1.8版本新增,应用于类型变量) |
ElementType.TYPE_USE | 1.8版本新增,应用于任何使用类型的语句中(例如声明语句、泛型和强制转换语句中的类型) |
2>@Retention
表明该注解的生命周期。
生命周期类型 | 描述 |
---|---|
RetentionPolicy.SOURCE | 编译时被丢弃,不包含在类文件中 |
RetentionPolicy.CLASS | JVM加载时被丢弃,包含在类文件中,默认值 |
RetentionPolicy.RUNTIME | 由JVM 加载,包含在类文件中,在运行时可以被获取到 |
3>@Documented
表明该注解标记的元素可以被Javadoc 或类似的工具文档化。
4>@Inherited
表明使用了@Inherited注解的注解,所标记的类的子类也会拥有这个注解@Target,@Retention,@Document,@Inherited
4)demo
//该注解可以应用于类、接口(包括注解类型)、枚举
@Target(ElementType.TYPE)
//该注解标记的元素可以被Javadoc 或类似的工具文档化
@Documented
//该注解的生命周期,由JVM 加载,包含在类文件中,在运行时可以被获取到
@Retention(RetentionPolicy.RUNTIME)
public @interface SystemConfig {
String name() default "lin";
int age();
}
//应用SystemConfig注解到User类
@SystemConfig(age = 20)
public class User {
private String name;
private Integer age;
}
public class AnnotationTest {
public static void main(String[] args) {
//获取User的Class对象
Class<?> userClass = User.class;
//判断Class对象上是否有SystemConfig的注解
if (userClass.isAnnotationPresent(SystemConfig.class)) {
System.out.println("User上配置了SystemConfig注解");
//获取SystemConfig注解
SystemConfig config = userClass.getAnnotation(SystemConfig.class);
System.out.println("SystemConfig.name:" + config.name() + "; SystemConfig.age:" + config.age());
} else {
System.out.println("User上没有配置SystemConfig注解");
}
}
}