注解管理Bean

这部分内容来自我的博客文章 《Spring:IOC之基于注解管理》

注解只是一个标记,作用是框架检测到注解标记的位置,然后针对这个位置按照注解标记的功能来执行具体操作。

要实现基于注解来管理bean,要先创建组件、再扫描组件,

通过注解+扫描,就可以将扫描的包下加上注解的类作为组件作为管理(其实就是在IOC容器内有了加上注解的这个类所对应的bean对象)

以下面这个例子为例 :

创建组件

创建控制层组件

1
2
3
@Controller
public class UserController {
}

扫描组件

扫描组件在配置文件中进行扫描,目的在于让Spring知道哪些类加了什么注解。

使用的标签是<context:component-scan> ,扫描的包通过 base-package字段指定。

分为三种情况 : 最基本的扫描方式、指定要排除的方式、指定要扫描的方式

  • 最基本的扫描

    1
    2
    3
    XML
    <context:component-scan base-package="com.atguigu">
    </context:component-scan>

基于注解的自动装配

基于注解的自动装配使用 @Autowired 注解实现。只需要在成员变量上添加 @Autowired 注解即可 :

注意 : 使用了该注解之后就不需要再写setter和getter方法了。

在基于xml管理bean的环节中,自动装配的方法是在配置文件中使用autowire字段

1
2
3
4
5
6
7
JAVA
@Controller
public class UserController {
@Autowired
private UserService userService;
...
}

而@Autowired的原理,其实就是通过 byType方式或 byName的方式来实现自动装配的效果。

实现@Autowired

测试文件

这是我们要实现的目标。写一个 annotationTest.xml 与 AnnotationBaseService.java ,分别为 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<bean id="bbs" class="com.minis.test.BaseBaseService">
<property type="com.minis.test.AServiceImpl" name="as" ref="aservice" />
</bean>
<bean id="aservice" class="com.minis.test.AServiceImpl">
<constructor-arg type="String" name="name" value="abc"/>
<constructor-arg type="int" name="level" value="3"/>
<property type="String" name="property1" value="Someone says"/>
<property type="String" name="property2" value="Hello World!"/>
<property type="com.minis.test.BaseService" name="ref1" ref="baseservice"/>
</bean>
<bean id="baseservice" class="com.minis.test.BaseService">
<!-- <property type="com.minis.test.BaseBaseService" name="bbs"
ref="basebaseservice" />-->
</bean>
</beans>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.minis.test;
//这里引入的beans.factory.annotation.Autowired类是我们需要实现的包
import com.minis.beans.factory.annotation.Autowired;
public class BaseService {
//添加了@Autowired注解,
@Autowired
private BaseBaseService bbs;
public BaseBaseService getBbs() {
return bbs;
}
public void setBbs(BaseBaseService bbs) {
this.bbs = bbs;
}
public BaseService() {
}
public void sayHello() {
System.out.println("Base Service says Hello");
bbs.sayHello();
}
}

可以看到,在上面的测试文件中,给BaseService中依赖的BaseBaseService添加上了 @Autowired注解,而在xml文件中并没有给BaseService添加上BaseBaseService的ref标签,这样一来想要实现程序,就是我们要实现的自动装配功能( @Autowired )。

解释注解

1
2
@Autowired
private BaseBaseService bbs;

注意,这个注解是添加在对象的实例域上的。

因此我们如果想解释这个注解,那么至少应该要等到这个对象创建好。

回顾一下bean创建的流程 :

  1. 读取xml配置文件,通过ClassPathXmlResource解析xml文件中的内容得到resource
  2. 定义一个SimpleBeanFactory类型的BeanFactory变量,并且把它赋给XmlBeanDefinitionReader,得到reader
  3. reader通过loadBeanDefinitions(resource)方法,把resource中的内容转化成我们需要的BeanDefinition并注册
  4. 以上完成了xml文件中的bean注册(但未生成bean实例)
  5. 在使用时,直接通过ClassPathXmlApplicationContext的getBean(beanName)方法获取
  6. getBean(beanName)方法在SimpleBeanFactory中实现,是一个三级缓存结构。如果没有实例且没有早期胚胎,则调用createBean(beanDefinition)创建单例bean。
  7. createBean(beanDefinition)中会先创造早期胚胎、再注入依赖,总之会返回一个bean实例
  8. 新注册这个bean实例 ,this.registerSingleton(beanName, singleton);
  9. 可以获取这个bean的值并使用其中的方法了。

因此我们解读注解的时机,就在7-8之间。而 refresh() 方法 ,是一个包装了整个 Bean 的创建过程,会调用getBean()方法,看一下getBean方法 :

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
public Object getBean(String beanName) throws BeansException {
//先尝试直接拿bean实例
Object singleton = this.getSingleton(beanName);
if (singleton == null) {
singleton = this.earlySingletonObjects.get(beanName);
//如果此时还没有这个bean的实例,则获取它的定义来创建实例
if (singleton == null) {
//获取bean的定义
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
singleton = createBean(beanDefinition);
//新注册这个bean实例
this.registerSingleton(beanName, singleton);
// 预留beanpostprocessor位置
// step 1: postProcessBeforeInitialization
// step 2: afterPropertiesSet
// step 3: init-method
// step 4: postProcessAfterInitialization

}
return singleton;
}
if (singleton == null){
throw new BeansException("bean is null");
}
return singleton;

}

要处理注解,则创建一个新的接口类 BeanPostProcessor,这个接口类里面 包含了两个方法,分别是在Bean初始化之前和Bean初始化之后,将这个接口类放入 config文件夹中。具体如下 :

1
2
3
4
5
6
7
8
9
10
11
package com.minis.beans.factory.config;

import com.minis.beans.BeansException;

public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

接着,定义好 @Autowired注解。这里定义的方式是在 autowired文件夹中新建一个Autowired.java程序。这里具体代码为

1
2
3
4
5
6
7
//指定了该注解的应用目标。在这种情况下,@Autowired 注解应用于类的字段(Field)。它表示被标记的字段需要进行自动装配。
@Target(ElementType.FIELD)
//指定了该注解的保留策略。在这种情况下,@Autowired 注解在运行时仍然可用。它表示该注解的信息将在运行时通过反射机制被保留和使用。
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {

}

根据上述定义可以知道,Autowired 修饰成员变量(属性),并且在运行时生效。

那么为了实现该注解 ,可以使用以下方法:运行时利用反射获取所有标注了 Autowired 注解的成员变量,把它初始化成一个 Bean,然后注入属性。

因此,结合前面我们定义的 BeanPostProcessor 接口,我们来定义 Autowired 的处理类 AutowiredAnnotationBeanPostProcessor,将其放在 annotation文件夹中。

从下面代码可以看出,属性名字很关键,我们就是靠它来获取和创建的 Bean。有了 Bean 之后,我们通过反射设置属性值,完成依赖注入。

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
46
47
48
49
50
51
52
53
54
55
56
57
package com.minis.beans.factory.annotation;

import com.minis.beans.BeansException;
import com.minis.beans.factory.config.BeanPostProcessor;
import com.minis.beans.factory.support.SimpleBeanFactory;

import java.lang.reflect.Field;

public class AutowiredAnnotationBeanPostProcessor implements BeanPostProcessor {
private SimpleBeanFactory beanFactory;

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
Object result = bean;

Class<?> clazz = result.getClass();
Field[] fields = clazz.getDeclaredFields();
if(fields!=null){
for(Field field : fields){
//对每一个属性进行判断,如果带有@Autowired注解则进行处理
// isAnnotationPresent() 是 Field 类的方法,用于检查该字段是否被指定的注解标记。在这里,它检查字段是否被 Autowired 注解标记。
boolean isAutowired = field.isAnnotationPresent(Autowired.class);
if(isAutowired){
String fieldName = field.getName();
//通过getBean() ,从bean工厂中获取对应的依赖对象
Object autowiredObj = this.getBeanFactory().getBean(fieldName);
try {
//将字段设置为可访问,以便能够修改私有字段。
field.setAccessible(true);
//将依赖对象注入到字段中。
field.set(bean, autowiredObj);
//打印日志,表示成功进行了自动注入。
System.out.println("autowire " + fieldName + " for bean " + beanName);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
return null;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return null;
}
public SimpleBeanFactory getBeanFactory() {
return beanFactory;
}

public void setBeanFactory(SimpleBeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
}

新的BeanFactory

在此之前我们已经定义了 BeanFactory 接口,以及一个 SimpleBeanFactory 的实现类。现在我们又需要引入另外一个 BeanFactory ————AutowireCapableBeanFactory,用于专为 Autowired 注入的 Bean 准备的。

基于代码复用、解耦的原则,我们可以对通用部分代码进行抽象,抽象出一个 AbstractBeanFactory 类,其中包括refresh()、getBean()、registerBeanDefinition() 等方法。因为这些方法提供了默认实现,确保这些方法即使不再被其他 BeanFactory 实现也能正常生效。

AbstractBeanFactory 的完整实现这里不再贴出,将其放在support文件夹中。

下面是其部分核心改动。

  1. 定义了抽象方法 applyBeanPostProcessorBeforeInitialization 与 applyBeanPostProcessorAfterInitialization,由名字可以看出,分别是在 Bean 处理类初始化之前和之后执行的方法。这两个方法交给具体的继承类去实现。
  2. 在 getBean() 方法中,在以前预留的位置,实现了对 Bean 初始化前、初始化和初始化后的处理。
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
46
47
48
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory,BeanDefinitionRegistry{
private Map<String,BeanDefinition> beanDefinitionMap=new ConcurrentHashMap<>(256);
private List<String> beanDefinitionNames=new ArrayList<>();
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

public AbstractBeanFactory() {
}

public Object getBean(String beanName) throws BeansException{
Object singleton = this.getSingleton(beanName);

if (singleton == null) {
singleton = this.earlySingletonObjects.get(beanName);
if (singleton == null) {
System.out.println("get bean null -------------- " + beanName);
BeanDefinition bd = beanDefinitionMap.get(beanName);
singleton=createBean(bd);
this.registerBean(beanName, singleton);

//beanpostprocessor
//step 1 : postProcessBeforeInitialization
applyBeanPostProcessorsBeforeInitialization(singleton, beanName);

//step 2 : init-method
if (bd.getInitMethodName() != null && !bd.getInitMethodName().equals("")) {
invokeInitMethod(bd, singleton);
}

//step 3 : postProcessAfterInitialization
applyBeanPostProcessorsAfterInitialization(singleton, beanName);
}

}
if (singleton == null) {
throw new BeansException("bean is null.");
}
return singleton;
}

......

abstract public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException;

abstract public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException;

}

由此,我们就可去实现AutowireCapableBeanFactory

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/**
* AutowireCapableBeanFactory 是一个扩展了 AbstractBeanFactory 的类,提供了自动装配的功能。
* 它管理了一个 AutowiredAnnotationBeanPostProcessor 实例的列表,用于在初始化 bean 时对其进行后处理。
*/
public class AutowireCapableBeanFactory extends AbstractBeanFactory {

// 存储 AutowiredAnnotationBeanPostProcessor 实例的列表
private final List<AutowiredAnnotationBeanPostProcessor> beanPostProcessors = new ArrayList<AutowiredAnnotationBeanPostProcessor>();

/**
* 将 AutowiredAnnotationBeanPostProcessor 实例添加到后处理器列表中。
* @param beanPostProcessor 要添加的 AutowiredAnnotationBeanPostProcessor 实例。
*/
public void addBeanPostProcessor(AutowiredAnnotationBeanPostProcessor beanPostProcessor) {
// 确保唯一性,先移除已存在的实例再添加新的实例
this.beanPostProcessors.remove(beanPostProcessor);
this.beanPostProcessors.add(beanPostProcessor);
}

/**
* 获取后处理器列表中 AutowiredAnnotationBeanPostProcessor 实例的数量。
* @return 后处理器列表中 AutowiredAnnotationBeanPostProcessor 实例的数量。
*/
public int getBeanPostProcessorCount() {
return this.beanPostProcessors.size();
}

/**
* 获取后处理器列表中 AutowiredAnnotationBeanPostProcessor 实例的列表。
* @return 后处理器列表中 AutowiredAnnotationBeanPostProcessor 实例的列表。
*/
public List<AutowiredAnnotationBeanPostProcessor> getBeanPostProcessors() {
return this.beanPostProcessors;
}

/**
* 在 bean 初始化之前应用 bean 后处理器。
* 调用所有 AutowiredAnnotationBeanPostProcessor 实例的 postProcessBeforeInitialization 方法。
* @param existingBean 初始化之前的 bean 实例。
* @param beanName bean 的名称。
* @return 应用后处理器后的 bean 实例。
* @throws BeansException 如果在后处理期间发生错误。
*/
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {

Object result = existingBean;
for (AutowiredAnnotationBeanPostProcessor beanProcessor : getBeanPostProcessors()) {
// 设置当前 AutowiredAnnotationBeanPostProcessor 的 bean 工厂
beanProcessor.setBeanFactory(this);
// 调用 bean 处理器的 postProcessBeforeInitialization 方法
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
// 如果处理结果为 null,立即返回
if (result == null) {
return result;
}
}
return result;
}

/**
* 在 bean 初始化之后应用 bean 后处理器。
* 调用所有 BeanPostProcessor 实例的 postProcessAfterInitialization 方法。
* @param existingBean 初始化之后的 bean 实例。
* @param beanName bean 的名称。
* @return 应用后处理器后的 bean 实例。
* @throws BeansException 如果在后处理期间发生错误。
*/
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {

Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
// 调用 bean 处理器的 postProcessAfterInitialization 方法
result = beanProcessor.postProcessAfterInitialization(result, beanName);
// 如果处理结果为 null,立即返回
if (result == null) {
return result;
}
}
return result;
}

}

调整 ClassPathXmlApplicationContext

最后则是调整 ClassPathXmlApplicationContext,引入的成员变量由 SimpleBeanFactory 改为新建的 AutowireCapableBeanFactory,并在构造函数里增加上下文刷新逻辑。

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
public class ClassPathXmlApplicationContext implements BeanFactory,ApplicationEventPublisher{
AutowireCapableBeanFactory beanFactory;
private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors =
new ArrayList<BeanFactoryPostProcessor>();

public ClassPathXmlApplicationContext(String fileName){
this(fileName, true);
}

public ClassPathXmlApplicationContext(String fileName, boolean isRefresh){
Resource res = new ClassPathXmlResource(fileName);
AutowireCapableBeanFactory bf = new AutowireCapableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
reader.loadBeanDefinitions(res);

this.beanFactory = bf;

if (isRefresh) {
try {
refresh();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (BeansException e) {
e.printStackTrace();
}
}
}

@Override
public Object getBean(String beanName) throws BeansException {
return this.beanFactory.getBean(beanName);
}

@Override
public Boolean containsBean(String name) {
return this.beanFactory.containsBean(name);
}

public void registerBean(String beanName, Object obj) {
this.beanFactory.registerBean(beanName, obj);
}

@Override
public void publishEvent(ApplicationEvent event) {
}

@Override
public boolean isSingleton(String name) {
// TODO Auto-generated method stub
return false;
}

@Override
public boolean isPrototype(String name) {
// TODO Auto-generated method stub
return false;
}

@Override
public Class<?> getType(String name) {
// TODO Auto-generated method stub
return null;
}

public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
return this.beanFactoryPostProcessors;
}

public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
this.beanFactoryPostProcessors.add(postProcessor);
}

public void refresh() throws BeansException, IllegalStateException {
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(this.beanFactory);

// Initialize other special beans in specific context subclasses.
onRefresh();
}

private void registerBeanPostProcessors(AutowireCapableBeanFactory bf) {
//if (supportAutowire) {
bf.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
//}
}

private void onRefresh() {
this.beanFactory.refresh();
}

}

小结

最后,我们来回顾一下完整的过程。

  1. 启动 ClassPathXmlApplicationContext 容器,执行 refresh()。

  2. 在 refresh 执行过程中,调用 registerBeanPostProcessors(),往 BeanFactory 里注册 Bean 处理器,如 AutowiredAnnotationBeanPostProcessor。

  3. 执行 onRefresh(), 执行 AbstractBeanFactory 的 refresh() 方法。

  4. AbstractBeanFactory 的 refresh() 获取所有 Bean 的定义,执行 getBean() 创建 Bean 实例。

  5. getBean() 创建完 Bean 实例后,调用 Bean 处理器并初始化。

    1
    2
    3
    applyBeanPostProcessorBeforeInitialization(singleton,  beanName);
    invokeInitMethod(beanDefinition, singleton);
    applyBeanPostProcessorAfterInitialization(singleton, beanName);
  6. applyBeanPostProcessorBeforeInitialization 由具体的 BeanFactory,如 AutowireCapableBeanFactory,来实现,,即对 BeanFactory 里已经注册好的所有 Bean 处理器调用相关方法。

    1
    2
    beanProcessor.postProcessBeforeInitialization(result,  beanName);
    beanProcessor.postProcessAfterInitialization(result, beanName);
  7. 我们事先准备好的 AutowiredAnnotationBeanPostProcessor 方法里面会解释 Bean 中的 Autowired 注解。