1. SpringIOC容器的设计
SpringIOC设计分为两条线。
- BeanFactroy==>HierachicalBeaFactroy==>ConfirationBeaFactroy 这条线可以理解成为SpringIOC容器的设计路线。
- BeanFactroy==>ListableBeanFactory==>ApplicationContext==>ConfigrableApplicationContext 这条是Spring上下文的设计路线。
之所以要这样分两条线,主要是要将容器和上下文区分开来。因为在Spring项目中,上下文对容器不仅是扩展关系,更重要的事持有关系,上下文是以属性的形式持有容器,开发者可以通过上下文对象获取容器。作者比较倾向于将二者区分开来理解,当然也可以理解上下文是容器的高级表现形式。
1.1 IOC 容器的设计路线
BeanFactory 定义了IOC容器的基本规范,包括getBean()按类型和名称获取Bean的方法。
HIerarchicalBeanFactory是在BeanFactory增加了getParentBeanFactory()方法,使BeanFactory具备了双亲IOC管理的功能。
ConfigurableBeanFactory接口是提供了配置BeanFactory的各种方法。比如setParentBeanFactroy()方法,配置上面提到的双亲IOC容器,addBeanProcessor()方法,配置Bean后置处理器等。
到ConfigurableBeanFactory接口为止,IOC容器还没有作为容器最基本的功能,那就是装东西。
1.2 应用上下问设计路线
上面说了应用上下文是IOC容器的高级表现形式,ListableBeanFactory具备了操作BeanDefinition的能力,比如getBeanDefinition()方法,可以获取Bean的总数。ApplicationContext类,实现的接口 如图所示:
- MessageRourse,支持不同的信息源。具备支持国际化的实现,为了开发多语言版本提供服务。
- ResourcePatternResolver,访问数据源,具备了从不同地方得到的Bean定义资源的能力,比如 xml、java config、注释 等等。
- ApplicationEventPublisher,发布事件。使应用上下文具备了事件的机制,事件机制为Bean声明周期的管理提供了便利。
WebApplicationContext 扩展了对Web应用的支持。
ConfigurableApplicationContext其中定义了一个重要的方法refresh方法。ConfigurableApplicationContext最重要的事扩展了配置上下文的功能,可控制上下文生命周期的能力等。
2. IOC容器的具体实现类DefaultListableBeanFactory
首先证明一点,为什么说DefaultListableBeanFactory类是具体的实现类。
随便启动一个SpringBoot项目找到getSpringFactoriesInstances代码那一行
/**
* Run the Spring application, creating and refreshing a new
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
// 记录程序运行时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// ConfigrableApplicationContext Spring的上下文
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
// 从MEATE-INFO/spring.factories中获取监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
// 1.获取并启动监听器
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 2. 构造容器环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 处理需要忽略的Bean
configureIgnoreBeanInfo(environment);
// 打印banner
Banner printedBanner = printBanner(environment);
// 初始化容器
context = createApplicationContext();
// 实例化SpringBootExceptionReporter.class,用来支持报告关于启动的错误
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 4.刷新容器前的准备阶段
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 5.刷新容器
refreshContext(context);
// 刷新容器后的扩展接口
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
IoC容器的真实面孔就是这个DefaultListableBeanFactory,它还有一个子类XmlBeanFactory,不过都已经被标注为弃用了。
2.1 作为IOC 容器的基础设计路线
ConfigurableListableBeanFactory接口主要是增加指定忽略类型和接口等
2.2 作为IOC容器的高级路线
- 设计路线:
BeanFactory => AutowireCapableBeanFactory =>AbstractAutowireCapableBeanFactory == DefaultListableBeanFactory
在这条线路中,AutowireCapableBeanFactory接口定义了自动注入bean(autowireBean())创建bean(createBean()) ,初始化bean(initializeBean())方法等。那么真正实现这些方法的类便是 AbstractAutowireCapableBeanFactory()。
AbsrtactAutoCapableBeanFactroy抽闲类中实现了AutoCapableBeanFactory接口定义的方法。在此基础上通过继承AbstractBeanFactory具备了操作Bean的能力。
SingletonBeanRegistry=>DefaultSingletonBeanRegistry=>FactoryBeanRegistrySupper=>AbstractBeanFactory=>AutowireCapableBeanFactory => DefaultListableBeanFactory
这个关系链中重点是SingletonBeanRegistry接口顾名思义,除了注册单例之外,还定义获取单例的方法。
注意:为什么只有 singleton的注册中心,而没有prototype类型的Bean的注册中心?因为单例Bean(singleton)是Spring帮我们创建并维护的,原型Bean(prototype) 是每次获取都会创建出来实例,本质是不同的。
3.
AliasRegistry=>SimpleAliasRegistry=>DefaultSingletonBeanRegistry=>FactroyBeanRegistry=>AbstractBeanFactory=>AutowireCapableBeanFactory=>DefaultListableBeanFactory
这条路线主要提供管理别称的能力。
AliasRegistry=>BeanDefinitionRegistry=>DefaultListableBeanFactory
BeanDefinitionRegistry接口是注册中心,使DefaultListableBeanFactory具备操作Beandefinition的能力。
2.3 DefaultListableBeanFactory几个重要的父类和接口
2.3.1 AbstractBeanFactory 抽象类
如上图所示,AbstarctBeanFactory中定义的几个重要方法 @Autowired @Resource(name = “xxx”) 一个是按类型获取一个是按名获取,具体的实现就是按照图上圈的几个方法。几个getBean()方法最终都是进入到doGetBean()方法,doGetBean()方法是实际获得bean的地方,也就是触发依赖注入的地方。
2.3.2 AbstractAutowireCapableBeanFactory抽象类
AbstractBeanFactory中实现类getBean()方法AbstractAutowireCapableBeanFactory中实现了bean的创建方法。
当我们需要定义一个Bean通常会这样写 @Bean(name=“test”,initMethod=“init”,destoryMethod=“destory”)
AbstractAutowireCapableBeanFactory中完成了一个Bean从create(createBean()) => createInstance(createBeanInstance()) => init(invokeInitMethods()) 的所有工作。所以这个抽象类的作用不言而喻。
2.3.3 DefaultSigletonBeanFactoryRegistry让IOC容器具有容器能力
通常理解的Spring容器,这个容器其实更多的是BeanFactory代表的意义:Bean的生产工厂,我们通常理解的容器就是用来装东西的,但是Spring容器不是代表类似现实中容器一样的东西,而是更像一个生产工厂,生产东西的地方,比如我们需要一个bean,只需要告诉Spring,它就会给我们,所以到现在为止我们还没有看到Spring的"容器"能力。
DefaultSingletonBeanRegistry属性如下
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/** Set of registered singletons, containing the bean names in registration order. */
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
/** Names of beans that are currently in creation. */
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
/** Names of beans currently excluded from in creation checks. */
private final Set<String> inCreationCheckExclusions =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
/** List of suppressed Exceptions, available for associating related causes. */
@Nullable
private Set<Exception> suppressedExceptions;
/** Flag that indicates whether we're currently within destroySingletons. */
private boolean singletonsCurrentlyInDestruction = false;
/** Disposable bean instances: bean name to disposable instance. */
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
/** Map between containing bean names: bean name to Set of bean names that the bean contains. */
private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);
/** Map between dependent bean names: bean name to Set of dependent bean names. */
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
/** Map between depending bean names: bean name to Set of bean names for the bean's dependencies. */
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
}
属性singletonObjects,就是这个属性最终存储单例(singleton)bean的地方
DefaultSingletonBeanRegistry上面提到的SingletonBeanRegsitry接口的相关方法,并且增加了很多对单例的操作方法。
2.3.4 DefaultListableBeanFactory
上面重IOC容器的宏观设计角度阐述了DefaultListableBeanFactory作为IOC容器的具体实现的设计思想。
以下是DefaultListableBeanFactory的属性
/** Map from serialized id to factory instance. */
// 缓存 序列化IDdao1 DefaultListableBeanFactory 实例的映射
private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
new ConcurrentHashMap<>(8);
/** Optional id for this factory, for serialization purposes. */
@Nullable
private String serializationId;
/** Whether to allow re-registration of a different definition with the same name. */
private boolean allowBeanDefinitionOverriding = true;
/** Whether to allow eager class loading even for lazy-init beans. */
private boolean allowEagerClassLoading = true;
/** Optional OrderComparator for dependency Lists and arrays. */
@Nullable
private Comparator<Object> dependencyComparator;
/** Resolver to use for checking if a bean definition is an autowire candidate. */
// 被用来去解决校验一个bean的定义是不是自动装载的候选
private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
/** Map from dependency type to corresponding autowired value. */
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);
/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);2
/** Map of singleton and non-singleton bean names, keyed by dependency type. */
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);
/** Map of singleton-only bean names, keyed by dependency type. */
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);
/** List of bean definition names, in registration order. */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
/** List of names of manually registered singletons, in registration order. */
private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);
/** Cached array of bean definition names in case of frozen configuration. */
@Nullable
private volatile String[] frozenBeanDefinitionNames;
/** Whether bean definition metadata may be cached for all beans. */
private volatile boolean configurationFrozen = false;
在Spring中,实际上是把DefaultListableBeanFactory作为一个默认功能完整的IOC容器来使用。DefaultListableBeanFactroy作为一个功能完整的容器具备了除以上父类所具有功能外,还加入对BeanDefinition的管理和维护。从上面的代码可以看到一个重要的属性:BeanDefinitionMap。
beanDefinitionMap缓存了Bean name到 BeanDefinition的映射。到这里是不是发现了Ioc容器另外一个作为"容器"的能力,总结一下这两个能力一个是装单例 (Singleton)Bean,一个是装BeanDefinition。
2.3.5 BeanDefinition
Spring通过定义BeanDefinition来管理基于Spring的应用中的各种对象以及他们之间的相互依赖关系。
BeanDefintion抽象了我们对Bean的定义,是让容器起作用的主要数据类型。在计算机世界里,所有的功能都是建立在通过数据对实现进行抽象的基础之上的。IOC容器是用来管理对象依赖关系的,对IOC容器来说,BeanDefinition就是对依赖反转模式中管理的对象依赖关系的数据抽象,也是容器实现依赖反转的数据结构,依赖反转功能都是围绕这个BeanDefinition的处理来完成的。这些BeanDefinition就像容器里装的水,有了这些基本数据,容器才能发挥作用。简单一句话来说,BeanDefintion就是Bean的元数据,BeanDefinition存放了对象Bean的基本描述,包括Bean有什么属性、方法、Bean的位置等等Bean的各种信息、IOC容器可以通过BeanDefinition生成Bean。