概述
Spring框架的核心就是IOC,通过controller一类注解的bean的实例化过程可以大体总结spring注解的工作原理:
1)利用asm技术扫描class文件,转化成Springbean结构,把符合扫描规则的(主要是是否有相关的注解标注,例如@Component)bean注册到Spring 容器中beanFactory。
2)注册处理器,包括注解处理器
3)实例化处理器(包括注解处理器),并将其注册到容器的beanPostProcessors列表中。
4)创建bean的过程中,属性注入或者初始化bean时会调用对应的注解处理器进行处理。
例如注解@Autowired:
对于这个注解,您需要在xml中配置这个注解的处理器AutowiredAnnotationBeanPostProcessor,这个处理器会扫描容器中所有的bean对象,发现bean中拥有@Autowired注解的时候会自动去找到容器中和这个注解修饰类型匹配的bean对象,并注入到对应的地方去。
元注解
@Target:表示该注释可以用于什么地方,下面是源码:
1
2
3
4
5
6
7
8
9
10
11
12
// 保留到运行时 (RetentionPolicy.RUNTIME)
(ElementType.ANNOTATION_TYPE)
public Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to.
*/
ElementType[] value();
}注解作用位置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22public enum ElementType {
TYPE, // 类,接口(包括注解),enum;
FIELD, // 属性域
METHOD, // 方法
PARAMETER, // 参数
CONSTRUCTOR, // 构造函数
LOCAL_VARIABLE, // 局部变量
ANNOTATION_TYPE, // 注解类型
PACKAGE, // 包
/**
* Type parameter declaration
* @since 1.8
*/
TYPE_PARAMETER, // 表明可以标注 类型参数
/**
* Use of a type
* @since 1.8
*/
TYPE_USE // 可以注解 任何类型名称
}@Retention 表示需要在什么级别保存该注释信息,下面是源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20/* Indicates how long annotations with the annotated type are to
* be retained. If no Retention annotation is present on
* an annotation type declaration, the retention policy defaults to
* {@code RetentionPolicy.CLASS}.
*
* A Retention meta-annotation has effect only if the
* meta-annotated type is used directly for annotation. It has no
* effect if the meta-annotated type is used as a member type in
* another annotation type.
*/
// 表明 注解会被包含在Java API文档中。
(RetentionPolicy.RUNTIME)
(ElementType.ANNOTATION_TYPE)
public Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}RetentionPolicy.SOURCE 保留在源码级别,被编译器抛弃,如@Override;
RetentionPolicy.CLASS 被编译器保留在编译后的class文件,但是被VM抛弃;
RetentionPolicy.RUNTIME 保留至运行时,可以被反射读取。如 @Retention 元注解本身。@Documented 将注释包含在JavaDoc中
@Inheried 允许子类继承父类中的注解
Java如何识别注解
关键词:Java反射
java.lang.reflect 包,实现反射功能的工具类
注解处理类库:java.lang.reflect.AnnotatedElement
程序通过反射获取了某个类的AnnotatedElement对象之后, 程序就可以调用该对象如下的方法来访问Annotation的信息:
Annotation[] getAnnotations()
1
2
3
4
5
6
7
8
9
10
11
12
13/**
* Returns annotations that are <em>present</em> on this element.
*
* If there are no annotations <em>present</em> on this element, the return
* value is an array of length 0.
*
* The caller of this method is free to modify the returned array; it will
* have no effect on the arrays returned to other callers.
*
* @return annotations present on this element
* @since 1.5
*/
Annotation[] getAnnotations();default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21/**
* Returns true if an annotation for the specified type
* is <em>present</em> on this element, else false. This method
* is designed primarily for convenient access to marker annotations.
*
* <p>The truth value returned by this method is equivalent to:
* {@code getAnnotation(annotationClass) != null}
*
* <p>The body of the default method is specified to be the code
* above.
*
* @param annotationClass the Class object corresponding to the
* annotation type
* @return true if an annotation for the specified annotation
* type is present on this element, else false
* @throws NullPointerException if the given annotation class is null
* @since 1.5
*/
default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
return getAnnotation(annotationClass) != null;
}default
T getDeclaredAnnotation(Class annotationClass) 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32/**
* Returns this element's annotation for the specified type if
* such an annotation is <em>directly present</em>, else null.
*
* This method ignores inherited annotations. (Returns null if no
* annotations are directly present on this element.)
*
* @implSpec The default implementation first performs a null check
* and then loops over the results of {@link
* #getDeclaredAnnotations} returning the first annotation whose
* annotation type matches the argument type.
*
* @param <T> the type of the annotation to query for and return if directly present
* @param annotationClass the Class object corresponding to the
* annotation type
* @return this element's annotation for the specified annotation type if
* directly present on this element, else null
* @throws NullPointerException if the given annotation class is null
* @since 1.8
*/
default <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
// Loop over all directly-present annotations looking for a matching one
for (Annotation annotation : getDeclaredAnnotations()) {
if (annotationClass.equals(annotation.annotationType())) {
// More robust to do a dynamic cast at runtime instead
// of compile-time only.
return annotationClass.cast(annotation);
}
}
return null;
}
为了处理注解,注解处理器做3件事情:
- 读取配置文件中管理的bean
- 实例化bean
- 注解处理器获取实例bean中的注解并操作
1 | // 自定义的注解处理器 |
Spring是如何实现注解的扫描注册的
管理注解bean定义的两个容器:
- AnnotationConfigApplicationContext
- AnnotationConfigWebApplicationContext
AnnotationConfigApplicationContext的源码:
1 | package org.springframework.context.annotation; |
AnnotationCnofigApplicationContext类的源码中的 “1 区”:
AnnotationConfigApplicationContext的基本功能在构造函数中完成
实例化reader和scanner,然后调用 register(Class<?>… annotatedClasses)或scan(String… basePackages)方法,最后刷新。
register(Class<?>… annotatedClasses)方法调用reader.register(Class<?>… annotatedClasses)
scan(String… basePackages)方法调用scanner.scan(String… basePackages)
AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner 功能类似,二者取其一。
AnnotationConfigApplicationContext 类的源码中的 “2 区”:
如下两个方法完成了Spring的扫描注册功能:
reader.register(Class<?>… annotatedClasses)
scanner.scan(String… basePackages)
reader.register(Class<?>… annotatedClasses) 的源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40public void register(Class<?>... annotatedClasses) {
for (Class<?> annotatedClass : annotatedClasses) {
registerBean(annotatedClass);
}
}
public void registerBean(Class<?> annotatedClass) {
registerBean(annotatedClass, null, (Class<? extends Annotation>[]) null);
}
// 注解功能实现区
"unchecked") (
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
} else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
} else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}scanner.scan(String… basePackages) 源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46public int scan(String... basePackages) {
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
doScan(basePackages); // 备注:重点关注此处
// Register annotation config processors, if necessary.
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
// 注解功能实现区
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
/**
* BeanDefinitionHoder: Holder for a BeanDefinition with name and aliases.
* BeanDefinition: A BeanDefinition describes a bean instance,
* which has property values, constructor argument values, and
* further information supplied by concrete implementations.
*/
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
for (String basePackage : basePackages) { // 多个包路径
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}