从Spring看框架设计原则
接口职责单一
在Spring依赖注入窗口的实现代码中,所有接口职责都非常单一,比如前面介绍过的BeanDefinitionRegistry,ResourceLoader,BeanFactory等,遵循了面向对象的单一职责原则,接口职责单一,使得不同接口之前可任意组合,分别扩展。如果需要对某一部分做扩展,则只需要提供该接口的新的实现,对其它接口无影响。例如ApplicationContext,前文提到过此接口相对BeanFactory有更丰富的功能,我们可先看看ApplicationContext的接口定义:

ApplicationContext接口的每一个父接口都是单一职责的定义。虽然ApplicationContext虽然继承了多个职责单一的接口,但ApplicationContext的实现类中并没有直接实现这些接口中的方法,而是通过代理模式的方式,将接口的实现代理到了成员变量上。我们可以再次打开AbstractApplicationContext类,看看此类的成员变量,可以看到ApplicationContext在其抽象实现类AbstractApplicationContext中对ResourcePatternResolver,
ListableBeanFactory, MessageSource等多个接口做了组合,如果需要对其中一个接口做扩展,只需要单独实现该接口,并组合进已有的ApplicationContext中即可。AbstractApplicationContext中的部分成员变量的定义如下图:

配置是编程的简化
由于我们最初使用Spring都是通过xml来配置(spring-boot不再需要),容易让人产生误解,认为spring是以配置为核心,实际上配置只是一种简化编程的方式,良好的设计上,可配置一定是可以编程的。
在Spring核心类之间的关系这一节中介绍了GenericApplicationContext类,这就是一个例子,我们可以完全通过编程的方式来使用GenericApplicationContext,但是手动编码创建BeanDefinition对象并注册到GenericApplicationContext中,整个过程非常复杂繁琐,当需要配置的bean非常多时,配置代码将变得非常冗长难以维护,Spring提供的xml配置的方式以及注解的方式为开发者提供了使用Spring更简单高效的方式。
核心流程可拦截
从初始化流程中,我们见到了Spring中BeanFactoryPostProcessor和BeanPostProcessor两个扩展接口, Spring提供的扩展接口还包括从这两个接口的子接口。作为一个通用框架,框架本身无法满足所有的场景,那就需要提供出足够多的扩展接口,Spring在初始化与bean的创建的核心流程中提供了PostProcessor接口,开发者可使用这些PostProcessor接口对Spring框架做扩展,实现特定意义的功能。

上面是个简单的例子,对bean做检查,如果Bean上打了@Log标签,则在日志中输出这个bean,只需要写一个类,实现BeanPostProcessor接口即可。BeanPostProcessor中有两个方法postProcessBeforeInitialization方法在bean初始化之前执行,postProcessAfterInitialization方法在bean初始化后执行。PostProcessor接口编写好后,可通过xml的<bean>或者注解中的@Component配置到Spring中即可。下面再来看看PostProcessor的类结构:

接口作用如下:
BeanPostProcessor:拦截bean的初始化,可对bean的初始化做前置处理和后置处理
InstantiationAwareBeanPostProcessor:拦截bean的创建和属性的注入,可对bean的创建做前置和后置处理,对属性注入之前做拦截
DestructionAwareBeanPostProcessor:对bean的销毁做拦截
MergedBeanDefinitionPostProcessor:对bean的定义做合并后的回调处理
BeanFactoryPostProcessor:用于对BeanFactory对象做定制处理,可通过它做一些属性的设置
BeanDefinitionRegistryPostProcessor:对BeanDefinitionRegistry做定制,比如注册某些特定的bean
其中BeanPostProcessor和BeanFactoryPostProcessor是两个最核心的扩展接口,其它扩展接口都是从这两个接口继承的,BeanPostProcessor及其子接口是对单个bean的初始化的拦截,BeanFactoryPostProcessor接口则是对所有bean整个的拦截,这些接口不仅仅只是给开发者扩展使用,在Spring自身的设计中都有丰富的应用场景,后文扩展接口的应用章节中将举例讲解Spring框架自身使用这些接口实现了哪些常用功能以及我们如何使用这些接口来实现特定的逻辑。
状态变化可事件广播
Spring的核心是依赖注入容器,而ApplicationContext为依赖注入容器的状态变化提供了事件广播机制。先看看ApplicationEvent的继承结构

ApplicationContext的实现类的默认构造器并不会广播ContextStartEvent,想要完整的执行广播,需要使用如下方式创建ApplicationContext:

扩展接口的应用
注解注入
Spring支持@Resource和@Autowire注解,用于对依赖的bean做自动注入,而Spring的核心逻辑中没有自去注入这个过程,自动注入是通过InstantiationAwareBeanPostProcessor接口完成的,具体实现类为AutowiredAnnotationBeanPostProcessor,注解注入的核心逻辑在postProcessPropertyValues方法中,下图是postProcessPropertyValues方法的实现,其中的逻辑比较简单,通过调用InjectionMetadata.inject()方法完成注解的注入,读者可自行阅读其中的详细实现代码。

AutowiredAnnotationBeanPostProcessor类中还提供了setAutowiredAnnotationType方法,用于指定通过哪个注解做注入,如果我们想实现自定义的注解做注入,可以基于此类和此方法做开发。

AOP代理的创建
AOP是通过动态代理实现的,动态代理对象的创建是通过AspectJAwareAdvisorAutoProxyCreator对象创建:

在wrapIfNecessary方法中创建的代理对象:

注解配置bean
对于@Configuration注解标识的类,ConfigurationClassPostProcessor会在BeanFactory创建后处理bean的配置:
