04 | 增强IoC容器:如何让我们的Spring支持注解?

大家好,我是郭屹。 在上一节课中,我们通过一系列操作使XML配置文件生效,并实现了Spring中的Bean构造器注入与setter注入。我们还引入了“早期毛胚Bean”的概念来解决循环依赖问题,并为容器增加了Spring中的核心方法refresh(),作为整个容器启动的入口。现在我们的容器已经有了基本的模型,接下来我们将让它变得更强大,从种子成长为一株幼苗。 在这节课中,我们将实现一个增强版的IoC容器,支持通过注解的方式进行依赖注入。注解是编程中常用的技术,它可以减少配置文件的内容,便于管理,同时提高开发效率。因此,我们将实现@Autowired注解,并使用这种方式进行依赖注入。

目录结构

我们手写MiniSpring的目的是为了更好地学习Spring。因此,我们会时不时地回头整理整个项目的目录结构,使其与Spring保持一致。 现在,我们参考Spring框架的结构,调整我们的项目结构,在beans目录下新增factory目录,factory目录中则新增xmlsupportconfigannotation四个目录。

1
2
3
4
5
6
├── beans
   └── factory
       ├── xml
       └── support
       └── config
       └── annotation

接下来将之前所写的类文件移动至新增目录下,你可以看一下移动后的结构。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
factory —— BeanFactory.java
factory.xml —— XmlBeanDefinitionReader.java
factory.support —— DefaultSingletonBeanRegistry.java
BeanDefinitionRegistry.javaSimpleBeanFactory.java
factory.config —— SingletonBeanRegistry.javaConstructorArgumentValues.java
ConstructorArgumentValue.javaBeanDefinition.java

// 注:
// ConstructorArgumentValues由ArgumentValues改名而来
// ConstructorArgumentValue由ArgumentValue改名而来

项目结构与Spring框架对比

在熟悉了本项目的结构之后,你可能会注意到它与Spring框架的结构非常相似。这种相似性不仅体现在目录结构上,还包括文件名、类中的主要方法名和属性名。这样的设计旨在帮助你在未来的学习过程中更加轻松地掌握Spring框架。

依赖注入与Autowired注解

如果你有使用Spring框架的经验,那么对@Autowired注解应该不会陌生。这是一种常用的依赖注入方式,通过在需要注入的对象上添加@Autowired注解来实现。以下是一个简单的示例,展示了如何使用@Autowired注解进行依赖注入。

1
2
3
4
public class Test {
  @Autowired
  private TestAutowired testAutowired;
}

在Spring框架中,注解提供了一种更为简洁的依赖注入方式,避免了在XML配置文件中显式使用ref属性指定依赖对象。然而,注解本身并不能自我解释,需要一个程序去解释它。以下是解释注解的步骤和时机:

1. 注解解释时机

注解是作用在实例变量上的,因此必须在对象创建后才能解释注解。在Spring框架中,Bean的创建过程被封装在refresh()方法中。Bean实例化之后,需要进行初始化工作,而refresh()方法中预留了三个阶段用于Bean的初始化处理:

  • postProcessBeforeInitialization:初始化前处理

  • init-method:执行自定义初始化方法

  • postProcessAfterInitialization:初始化后处理 这些阶段是解释注解的理想时机。

2. BeanPostProcessor的作用

为了在这些阶段解释注解,我们可以使用BeanPostProcessor。BeanPostProcessor有两个方法,分别用于处理Bean初始化之前和之后:

  • postProcessBeforeInitialization:在Bean初始化之前调用,可以在此方法中解释注解并进行相应的处理。

  • postProcessAfterInitialization:在Bean初始化之后调用,可以在此方法中进行注解解释后的后续处理。 通过定义BeanPostProcessor并实现这两个方法,我们可以在Bean的生命周期中的适当时机解释注解,并实现依赖注入等操作。

1
2
3
4
public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object bean, String beanName) throws
BeansException;
}
  1. Bean初始化之后
1
2
3
4
public interface BeanPostProcessor {
    Object postProcessAfterInitialization(Object bean, String beanName) throws
BeansException;
}

接下来我们定义Autowired注解,很简单,你可以参考一下。

1
2
3
4
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}

在Spring框架中,@Autowired注解用于自动装配依赖。当我们想要实现@Autowired这个功能时,可以考虑通过反射机制来获取所有标记了@Autowired注解的成员变量,并将这些成员变量初始化为相应的Bean对象,随后进行属性注入。

为了达到这样的目的,我们可以结合之前提到的BeanPostProcessor接口来创建一个处理类AutowiredAnnotationBeanPostProcessor。该处理类将在Bean实例化之后但在初始化方法调用之前运行,从而确保在合适的时候执行自动装配逻辑。

以下是使用BeanPostProcessor接口定义AutowiredAnnotationBeanPostProcessor的一个概览:

  1. 实现BeanPostProcessor接口。
  2. postProcessBeforeInitializationpostProcessAfterInitialization方法中(根据需要选择),利用反射技术扫描被创建的Bean对象的所有字段。
  3. 检查每个字段是否带有@Autowired注解。
  4. 对于带有@Autowired注解的字段,找到合适的Bean并将其注入到当前字段中。
  5. 返回处理后的Bean对象。 这样,我们就可以通过自定义的BeanPostProcessor实现类似于Spring框架内部对@Autowired注解的支持了。
 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
public class AutowiredAnnotationBeanPostProcessor implements BeanPostProcessor {
    private AutowireCapableBeanFactory beanFactory;

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

        Class<?> clazz = bean.getClass();
        Field[] fields = clazz.getDeclaredFields();
        if(fields!=null){
            //对每一个属性进行判断,如果带有@Autowired注解则进行处理
            for(Field field : fields){
                boolean isAutowired =
field.isAnnotationPresent(Autowired.class);
                if(isAutowired){
                    //根据属性名查找同名的bean
                    String fieldName = field.getName();
                    Object autowiredObj =
this.getBeanFactory().getBean(fieldName);
                    //设置属性值,完成注入
                    try {
                        field.setAccessible(true);
                        field.set(bean, autowiredObj);
                        System.out.println("autowire " + fieldName + " for bean
" + beanName);
                    }
                }
            }
        }
        return result;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
        return null;
    }
    public AutowireCapableBeanFactory getBeanFactory() {
        return beanFactory;
    }
    public void setBeanFactory(AutowireCapableBeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }
}

其实,核心代码就只有几行。

1
2
3
4
5
6
boolean isAutowired = field.isAnnotationPresent(Autowired.class);
if(isAutowired){
    String fieldName = field.getName();
    Object autowiredObj =  this.getBeanFactory().getBean(fieldName);
    field.setAccessible(true);
    field.set(bean, autowiredObj);

判断类里面的每一个属性是不是带有Autowired注解,如果有,就根据属性名获取Bean。从这里我们可以看出,属性名字很关键,我们就是靠它来获取和创建的Bean。有了Bean之后,我们通过反射设置属性值,完成依赖注入。

新的BeanFactory

在这里我们引入了AutowireCapableBeanFactory,这个BeanFactory就是专为Autowired注入的Bean准备的。

在此之前我们已经定义了BeanFactory接口,以及一个SimpleBeanFactory的实现类。现在我们又需要引入另外一个BeanFactory—— AutowireCapableBeanFactory。基于代码复用、解耦的原则,我们可以对通用部分代码进行抽象,抽象出一个AbstractBeanFactory类。

目前,我们可以把refresh()、getBean()、registerBeanDefinition()等方法提取到抽象类,因为我们提供了默认实现,确保这些方法即使不再被其他BeanFactory实现也能正常生效。改动比较大,所以这里我贴出完整的类代码,下面就是AbstractBeanFactory的完整实现。

  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
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
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<>(16);
    public AbstractBeanFactory() {
    }
    public void refresh() {
        for (String beanName : beanDefinitionNames) {
            try {
                getBean(beanName);
            }
        }
    }
    @Override
    public Object getBean(String beanName) throws BeansException {
        //先尝试直接从容器中获取bean实例
        Object singleton = this.getSingleton(beanName);
        if (singleton == null) {
            //如果没有实例,则尝试从毛胚实例中获取
            singleton = this.earlySingletonObjects.get(beanName);
            if (singleton == null) {
                //如果连毛胚都没有,则创建bean实例并注册
                System.out.println("get bean null -------------- " + beanName);
                BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
                singleton = createBean(beanDefinition);
                this.registerBean(beanName, singleton);
                // 进行beanpostprocessor处理
                // step 1: postProcessBeforeInitialization
                applyBeanPostProcessorBeforeInitialization(singleton, beanName);
                // step 2: init-method
                if (beanDefinition.getInitMethodName() != null &&
!beanDefinition.equals("")) {
                    invokeInitMethod(beanDefinition, singleton);
                }
                // step 3: postProcessAfterInitialization
                applyBeanPostProcessorAfterInitialization(singleton, beanName);
            }
        }

        return singleton;
    }
    private void invokeInitMethod(BeanDefinition beanDefinition, Object obj) {
        Class<?> clz = beanDefinition.getClass();
        Method method = null;
        try {
            method = clz.getMethod(beanDefinition.getInitMethodName());
        }
        try {
            method.invoke(obj);
        }
    }
    @Override
    public Boolean containsBean(String name) {
        return containsSingleton(name);
    }
   public void registerBean(String beanName, Object obj) {
        this.registerSingleton(beanName, obj);
    }
    @Override
    public void registerBeanDefinition(String name, BeanDefinition
beanDefinition) {
        this.beanDefinitionMap.put(name, beanDefinition);
        this.beanDefinitionNames.add(name);
        if (!beanDefinition.isLazyInit()) {
            try {
                getBean(name);
            }
        }
    }
    @Override
    public void removeBeanDefinition(String name) {
        this.beanDefinitionMap.remove(name);
        this.beanDefinitionNames.remove(name);
        this.removeSingleton(name);
    }
    @Override
    public BeanDefinition getBeanDefinition(String name) {
        return this.beanDefinitionMap.get(name);
    }
    @Override
    public boolean containsBeanDefinition(String name) {
        return this.beanDefinitionMap.containsKey(name);
    }
    @Override
    public boolean isSingleton(String name) {
        return this.beanDefinitionMap.get(name).isSingleton();
    }
    @Override
    public boolean isPrototype(String name) {
        return this.beanDefinitionMap.get(name).isPrototype();
    }
    @Override
    public Class<?> getType(String name) {
        return this.beanDefinitionMap.get(name).getClass();
    }
    private Object createBean(BeanDefinition beanDefinition) {
        Class<?> clz = null;
        //创建毛胚bean实例
        Object obj = doCreateBean(beanDefinition);
        //存放到毛胚实例缓存中
        this.earlySingletonObjects.put(beanDefinition.getId(), obj);
        try {
            clz = Class.forName(beanDefinition.getClassName());
        }
        //完善bean,主要是处理属性
        populateBean(beanDefinition, clz, obj);
        return obj;
    }
    //doCreateBean创建毛胚实例,仅仅调用构造方法,没有进行属性处理
    private Object doCreateBean(BeanDefinition beanDefinition) {
        Class<?> clz = null;
        Object obj = null;
        Constructor<?> con = null;
        try {
            clz = Class.forName(beanDefinition.getClassName());
            // handle constructor
            ConstructorArgumentValues constructorArgumentValues =
beanDefinition.getConstructorArgumentValues();
            if (!constructorArgumentValues.isEmpty()) {
                Class<?>[] paramTypes = new Class<?>
[constructorArgumentValues.getArgumentCount()];
                Object[] paramValues = new
Object[constructorArgumentValues.getArgumentCount()];
                for (int i = 0; i <
constructorArgumentValues.getArgumentCount(); i++) {
                    ConstructorArgumentValue constructorArgumentValue =
constructorArgumentValues.getIndexedArgumentValue(i);
                    if ("String".equals(constructorArgumentValue.getType()) ||
"java.lang.String".equals(constructorArgumentValue.getType())) {
                        paramTypes[i] = String.class;
                        paramValues[i] = constructorArgumentValue.getValue();
                    } else if
("Integer".equals(constructorArgumentValue.getType()) ||
"java.lang.Integer".equals(constructorArgumentValue.getType())) {
                        paramTypes[i] = Integer.class;
                        paramValues[i] = Integer.valueOf((String)
constructorArgumentValue.getValue());
                    } else if ("int".equals(constructorArgumentValue.getType()))
{
                        paramTypes[i] = int.class;
                        paramValues[i] = Integer.valueOf((String)
constructorArgumentValue.getValue());
                    } else {
                        paramTypes[i] = String.class;
                        paramValues[i] = constructorArgumentValue.getValue();
                    }
                }
                try {
                    con = clz.getConstructor(paramTypes);
                    obj = con.newInstance(paramValues);
                }
            }
        }
        System.out.println(beanDefinition.getId() + " bean created. " +
beanDefinition.getClassName() + " : " + obj.toString());
        return obj;
    }
    private void populateBean(BeanDefinition beanDefinition, Class<?> clz,
Object obj) {
        handleProperties(beanDefinition, clz, obj);
    }
    private void handleProperties(BeanDefinition beanDefinition, Class<?> clz,
Object obj) {
        // handle properties
        System.out.println("handle properties for bean : " +
beanDefinition.getId());
        PropertyValues propertyValues = beanDefinition.getPropertyValues();
        //如果有属性
        if (!propertyValues.isEmpty()) {
            for (int i = 0; i < propertyValues.size(); i++) {
                PropertyValue propertyValue =
propertyValues.getPropertyValueList().get(i);
                String pType = propertyValue.getType();
                String pName = propertyValue.getName();
                Object pValue = propertyValue.getValue();
                boolean isRef = propertyValue.getIsRef();
                Class<?>[] paramTypes = new Class<?>[1];
                Object[] paramValues = new Object[1];
                if (!isRef) { //如果不是ref,只是普通属性
                    //对每一个属性,分数据类型分别处理
                    if ("String".equals(pType) ||
"java.lang.String".equals(pType)) {
                        paramTypes[0] = String.class;
                    } else if ("Integer".equals(pType) ||
"java.lang.Integer".equals(pType)) {
                        paramTypes[i] = Integer.class;
                    } else if ("int".equals(pType)) {
                        paramTypes[i] = int.class;
                    } else {
                        paramTypes[i] = String.class;
                    }
                    paramValues[0] = pValue;
                } else {//is ref, create the dependent beans
                    try {
                        paramTypes[0] = Class.forName(pType);
                    }
                    try {//再次调用getBean创建ref的bean实例
                        paramValues[0] = getBean((String) pValue);
                    }
                }
                //按照setXxxx规范查找setter方法,调用setter方法设置属性
                String methodName = "set" + pName.substring(0, 1).toUpperCase()
+ pName.substring(1);
                Method method = null;
                try {
                    method = clz.getMethod(methodName, paramTypes);
                }
                try {
                    method.invoke(obj, paramValues);
                }
            }
        }
    }
    abstract public Object applyBeanPostProcessorBeforeInitialization(Object
existingBean, String beanName) throws BeansException;
    abstract public Object applyBeanPostProcessorAfterInitialization(Object
existingBean, String beanName) throws BeansException;
}

上面的代码较长,但仔细一看可以发现绝大多数是我们原本已经实现的方法,只是移动到了AbstractBeanFactory这个抽象类之中。最关键的代码是getBean()中的这一段。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
singleton = createBean(beanDefinition);
this.registerBean(beanName, singleton);

// beanpostprocessor
// step 1: postProcessBeforeInitialization
applyBeanPostProcessorBeforeInitialization(singleton, beanName);
// step 2: init-method
if (beanDefinition.getInitMethodName() != null &&
!beanDefinition.equals("")) {
    invokeInitMethod(beanDefinition, singleton);
}
// step 3: postProcessAfterInitialization
applyBeanPostProcessorAfterInitialization(singleton, beanName);

在Spring框架中,Bean的生命周期包括获取Bean的定义、创建Bean实例以及进行Bean的后处理和初始化。在这个抽象类里,我们关注两个核心改动:

  1. 定义了抽象方法applyBeanPostProcessorBeforeInitialization与applyBeanPostProcessorAfterInitialization:这两个方法分别在Bean处理类初始化之前和之后执行。具体的实现由继承该抽象类的子类来完成。

  2. 在getBean()方法中实现了对Bean初始化前、初始化和初始化后的处理

  • 在Bean初始化前调用applyBeanPostProcessorBeforeInitialization方法。
  • 完成Bean的初始化。
  • 在Bean初始化后调用applyBeanPostProcessorAfterInitialization方法。 通过这些改动,我们可以灵活地在Bean的整个生命周期中插入自定义的处理逻辑,从而满足不同的业务需求。
1
2
3
4
5
6
7
8
  // step 1: postProcessBeforeInitialization
  applyBeanPostProcessorBeforeInitialization(singleton, beanName);
  // step 2: init-method
  if (beanDefinition.getInitMethodName() != null && !beanDefinition.equals("")) {
      invokeInitMethod(beanDefinition, singleton);
  }
  // step 3: postProcessAfterInitialization
  applyBeanPostProcessorAfterInitialization(singleton, beanName);

现在已经抽象出了一个AbstractBeanFactory,接下来我们看看具体的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
public class AutowireCapableBeanFactory extends AbstractBeanFactory{
    private final List<AutowiredAnnotationBeanPostProcessor> beanPostProcessors =
new ArrayList<>();
    public void addBeanPostProcessor(AutowiredAnnotationBeanPostProcessor
beanPostProcessor) {
        this.beanPostProcessors.remove(beanPostProcessor);
        this.beanPostProcessors.add(beanPostProcessor);
    }
    public int getBeanPostProcessorCount() {
        return this.beanPostProcessors.size();
    }
    public List<AutowiredAnnotationBeanPostProcessor> getBeanPostProcessors() {
        return this.beanPostProcessors;
    }
    public Object applyBeanPostProcessorsBeforeInitialization(Object
existingBean, String beanName) throws BeansException {
        Object result = existingBean;
        for (AutowiredAnnotationBeanPostProcessor beanProcessor :
getBeanPostProcessors()) {
            beanProcessor.setBeanFactory(this);
            result = beanProcessor.postProcessBeforeInitialization(result,
beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean,
String beanName) throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            result = beanProcessor.postProcessAfterInitialization(result,
beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }
}

从代码里也可以看出,它实现起来并不复杂,用一个列表beanPostProcessors记录所有的Bean处理器,这样可以按照需求注册若干个不同用途的处理器,然后调用处理器。

1
2
3
4
5
6
for (AutowiredAnnotationBeanPostProcessor beanProcessor :
getBeanPostProcessors()) {
    beanProcessor.setBeanFactory(this);
    result = beanProcessor.postProcessBeforeInitialization(result,
beanName);
}

代码一目了然,就是对每个Bean处理器,调用方法postProcessBeforeInitialization。

最后则是调整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
public ClassPathXmlApplicationContext(String fileName, boolean isRefresh) {
        Resource resource = new ClassPathXmlResource(fileName);
        AutowireCapableBeanFactory beanFactory = new
AutowireCapableBeanFactory();
        XmlBeanDefinitionReader reader = new
XmlBeanDefinitionReader(beanFactory);
        reader.loadBeanDefinitions(resource);
        this.beanFactory = beanFactory;
        if (isRefresh) {
            try {
                refresh();
            }
        }
    }

    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
beanFactory) {
        beanFactory.addBeanPostProcessor(new
AutowiredAnnotationBeanPostProcessor());
    }
    private void onRefresh() {
        this.beanFactory.refresh();
    }

在Spring框架中,ClassPathXmlApplicationContext容器的启动过程涉及到了Bean的初始化和依赖注入。以下是该过程的一个有条理且结构化的描述:

  1. 启动容器
  • 创建并初始化ClassPathXmlApplicationContext实例。

  • 调用refresh()方法来启动容器刷新过程。

  1. 注册BeanPostProcessor
  • refresh()方法执行过程中,会调用registerBeanPostProcessors()

  • 此步骤负责向内部的BeanFactory注册各种BeanPostProcessor,例如AutowiredAnnotationBeanPostProcessor,这些处理器用于处理特定注解,如@Autowired等。

  1. 执行onRefresh()
  • refresh()方法接下来将调用onRefresh()方法。

  • 这一步通常由子类实现具体逻辑,比如加载或预处理配置元数据。

  1. 获取Bean定义与创建Bean实例
  • AbstractBeanFactory中的refresh()方法会被调用,以确保所有的bean定义已经被正确加载。

  • 随后,通过getBean()方法根据需要创建bean实例。

  • getBean()不仅创建bean对象,还会解决bean之间的依赖关系。

  1. 应用BeanPostProcessor进行初始化
  • bean实例创建完成后,之前注册的BeanPostProcessor们会被用来进一步处理这些bean。

  • 包括但不限于属性填充、AOP代理等操作,最终完成bean的初始化工作。

此流程展示了Spring如何通过一系列精心设计的方法链来保证应用程序上下文能够被正确地构建,并准备好供应用程序使用。

1
2
3
applyBeanPostProcessorBeforeInitialization(singleton, beanName);
invokeInitMethod(beanDefinition, singleton);
applyBeanPostProcessorAfterInitialization(singleton, beanName);
  1. applyBeanPostProcessorBeforeInitialization由具体的BeanFactory,如AutowireCapableBeanFactory,来实现,这个实现也很简单,就是对BeanFactory里已经注册好的所有Bean处理器调用相关方法。
1
2
beanProcessor.postProcessBeforeInitialization(result, beanName);
beanProcessor.postProcessAfterInitialization(result, beanName);
  1. 我们事先准备好的AutowiredAnnotationBeanPostProcessor方法里面会解释Bean中的Autowired注解。

测试注解

到这里,支持注解的工作就完成了,接下来就是测试Autowired注解了。在这里我们做两个改动。

  1. 在测试类中增加Autowired注解。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package com.minis.test;
import com.minis.beans.factory.annotation.Autowired;
public class BaseService {
    @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();
    }
}
  1. 注释XML配置文件中关于循环依赖的配置。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?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>

这节课我们丰富了原来的框架,支持了注解,让它更有模有样了。 注解是现代最受程序员欢迎的特性,我们通过Autowired这个注解实现了Bean的注入,这样程序员不用再在XML配置文件中手动配置property,而是在类中声明property的时候直接加上注解即可,框架使用的机制是名称匹配,这也是Spring所支持的一种匹配方式。 接着我们提取了BeanFactory接口,定义了一个抽象的AbstractBeanFactory。通过这个抽象类,将Bean工厂需要做的事情的框架搭建出来,然后在具体实现类中完善细节。这种程序结构称为interface-abstract class-class(接口抽象类),是一种做框架时常用的设计模式。

MiniSpring 自学项目

目标

通过手写 MiniSpring,我们不仅学习功能实现,还要学习大师的编码风格,模仿他们的代码和设计。通过大量练习,我们能够像专业程序员一样编写代码。

源代码

完整源代码可以在以下链接找到:MiniSpring GitHub

功能概览

以下是 MiniSpring 的一些核心功能:

  • GitHub Copilot: 利用 AI 编写更好的代码。

  • Security: 查找并修复安全漏洞。

  • Actions: 自动化任何工作流程。

  • Codespaces: 提供即时的开发环境。

  • Issues: 规划和跟踪工作。

  • Code Review: 管理代码变更。

  • Discussions: 在代码之外进行协作。

  • Code Search: 减少搜索,发现更多。

资源探索

  • Learning Pathways: 学习路径。

  • White papers, Ebooks, Webinars: 白皮书、电子书、网络研讨会。

  • Customer Stories: 客户故事。

  • Partners: 合作伙伴。

GitHub Sponsors

支持开源开发者的平台。

阅读材料

  • The ReadME Project: GitHub 社区文章。

企业平台

  • Enterprise platform: AI 驱动的开发者平台。

定价

  • Pricing: 查看定价信息。

功能特性

  • Provide feedback: 提供反馈。

  • Saved searches: 保存搜索,以便更快地过滤结果。

课后思考题

学完这节课后,我留给你一个思考题:在现有框架中,我们实现了 Autowired 注解,能否支持多个注解?欢迎在留言区与我交流讨论,也欢迎你把这节课分享给需要的朋友。我们下节课见!