3.1 依赖查找
-
根据 Bean 名称查找
-
实时查找(getBean("xxx"))
-
延迟查找(ObjectFactory)
-
-
根据 Bean 类型查找
-
单个 Bean 对象(getBean(xxx.class))
-
集合 Bean 对象(getBeansByType(xxx.class))
-
-
根据 Bean 名称 + 类型查找(getBean("xxx", xxx.class))
-
根据 Java 注解查找(getBeansWithAnnotation(xxx.class))
-
单个 Bean 对象
-
集合 Bean对象
-
3.2 依赖注入
-
根据 Bean 名称注入(ref="xxx"或者autowire="byName")
-
根据 Bean 类型注入
-
单个 Bean 对象
-
集合 Bean 对象(util:list、util:set等,autowire="byType")
-
-
注入容器内建 Bean 对象(Environment等)
-
注入非 Bean 对象(BeanFactory、ApplicationContext等)
-
注入类型
-
实时注入
-
延迟注入(ObjectFactory)
-
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<!-- 集合注入,通过类型注入 -->
<bean id="userRepository" class="xxx.xxx.xxx.UserRepository" autowire="byType"/>
<!--
<property name="users">
<util:list>
<ref bean="superUser"/>
<ref bean="user"/>
</util:list>
</property>
-->
</beans>
3.3 依赖来源
-
自定义 Bean(XML、注解等)
-
容器内建 Bean 对象(environment对象等,通过手动注册BeanDefinition)
-
容器内建依赖(BeanFactory等,直接添加到BeanFactory中)
3.4 配置元信息
-
Bean 定义配置(BeanDefinition)
-
基于 XML 文件
-
基于 Properties 文件
-
基于 Java 注解
-
基于 Java API
-
-
IoC 容器配置
-
基于 XML 文件
-
基于 Java 注解
-
基于 Java API
-
-
外部化配置(@Value)
-
基于 Java 注解
-
3.5 BeanFactory和ApplicationContext
ApplicationContext 是 BeanFactory 子接口,功能上是 BeanFactory 的超集,并且在AbstractRefreshableApplicationContext 中通过组合的方式将 BeanFactory 组合进来,通过代理的方式将 BeanFactory 重写的方法指定给内部组合的 BeanFactory 来执行,比如在 AbstractApplicationContext 中 getBean()
方法都是这样实现的:
//---------------------------------------------------------------------
// Implementation of BeanFactory interface
//---------------------------------------------------------------------
@Override
public Object getBean(String name) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name, requiredType);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name, args);
}
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(requiredType);
}
@Override
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(requiredType, args);
}
@Override
public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType) {
assertBeanFactoryActive();
return getBeanFactory().getBeanProvider(requiredType);
}
@Override
public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType) {
assertBeanFactoryActive();
return getBeanFactory().getBeanProvider(requiredType);
}
@Override
public boolean containsBean(String name) {
return getBeanFactory().containsBean(name);
}
@Override
public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
assertBeanFactoryActive();
return getBeanFactory().isSingleton(name);
}
@Override
public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
assertBeanFactoryActive();
return getBeanFactory().isPrototype(name);
}
@Override
public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException {
assertBeanFactoryActive();
return getBeanFactory().isTypeMatch(name, typeToMatch);
}
@Override
public boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
assertBeanFactoryActive();
return getBeanFactory().isTypeMatch(name, typeToMatch);
}
@Override
@Nullable
public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
assertBeanFactoryActive();
return getBeanFactory().getType(name);
}
@Override
@Nullable
public Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException {
assertBeanFactoryActive();
return getBeanFactory().getType(name, allowFactoryBeanInit);
}
@Override
public String[] getAliases(String name) {
return getBeanFactory().getAliases(name);
}
即 BeanFactory 是 Spring 最基本的容器,ApplicationContext 拥有 BeanFactory 所有功能,是 BeanFactory 的超集,同时还有许多自身特有的功能,功能在下一小节叙述。
3.6 ApplicationContext作用
ApplicationContext 除了提供 IoC 容器角色,还提供以下功能:
-
面向切面(AOP)
-
配置元信息(Configuration Metadata)
-
资源管理(Resources)
-
事件(Event)
-
国际化(i18n)
-
注解(Annotation)
-
Environment 抽象(Environment Abstraction)
3.7 BeanFactory 和 ApplicationContext选择
-
BeanFactory 是 Spring 的底层 IoC 容器
-
ApplicationContext 是具备应用特性的 BeanFactory 超集
3.7.1 BeanFactory使用
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
int beanDefinitionCount = reader.loadBeanDefinitions("classpath:spring.xml");
// 接下来就能使用factory了
3.7.2 ApplicationContext使用
@Configuration
public class AnnotationContextAsIoCContainerDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 注册配置类
context.register(AnnotationContextAsIoCContainerDemo.class);
context.refresh();
// 接下来就能使用context了
}
@Bean
public User user() {
return new User("foo", 18);
}
}
3.8 IOC 容器启停过程
3.8.1 启动
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
// 记录启动时间,初始化PropertiySources,校验Environment对象等
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 创建BeanFactory -> DefaultListableBenaFactory,在AbstractRefreshableApplicationContext中创建,此处只完成实例化,还未完成初始化
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 添加一些内建的bean(environment、systemProperties等)以及依赖(BeanFactory、ResourceLoader等)
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 注册针对容器的扩展点(对容器进行调整)
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
// 调用针对容器的扩展点
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册针对bean的扩展点(对bean进行调整)
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
// 初始化国际化信息
initMessageSource();
// Initialize event multicaster for this context.
// 初始化事件发布
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
// 注册监听
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 实例化所有单例对象
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 发布事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
contextRefresh.end();
}
}
}
3.8.3 停止
public void close() {
synchronized (this.startupShutdownMonitor) {
// 关闭
doClose();
// If we registered a JVM shutdown hook, we don't need it anymore now:
// We've already explicitly closed the context.
if (this.shutdownHook != null) {
try {
// 移除shutdownhook
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
}
catch (IllegalStateException ex) {
// ignore - VM is already shutting down
}
}
}
}
protected void doClose() {
// Check whether an actual close attempt is necessary...
if (this.active.get() && this.closed.compareAndSet(false, true)) {
if (logger.isDebugEnabled()) {
logger.debug("Closing " + this);
}
if (!NativeDetector.inNativeImage()) {
LiveBeansView.unregisterApplicationContext(this);
}
try {
// Publish shutdown event.
publishEvent(new ContextClosedEvent(this));
}
catch (Throwable ex) {
logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
}
// Stop all Lifecycle beans, to avoid delays during individual destruction.
if (this.lifecycleProcessor != null) {
try {
this.lifecycleProcessor.onClose();
}
catch (Throwable ex) {
logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
}
}
// Destroy all cached singletons in the context's BeanFactory.
// 销毁所有Bean
destroyBeans();
// Close the state of this context itself.
// 关闭所有BeanFactory
closeBeanFactory();
// Let subclasses do some final clean-up if they wish...
onClose();
// Reset local application listeners to pre-refresh state.
if (this.earlyApplicationListeners != null) {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Switch to inactive.
this.active.set(false);
}
}
3.9 面试题
3.9.1 什么是 Spring IOC 容器
依赖注入、依赖查找以及一些其他特性共同构成了 Spring IOC 容器,官方答案如下:
Spring 框架实现 IoC 原则,IoC 也称之为 DI(依赖注入,此处官方文档有点不太严谨,因为 IoC 不只是依赖注入,还有依赖查找),这个过程会伴随状态的依赖,此处主要指通过构造器参数、工厂方法或者是属性的setter方法去注入一些其他的对象,从而实现依赖注入,容器会将依赖注入的信息放到创建的 Bean 中来。Spring 框架是一个 IoC 容器的实现,DI 是它的实现原则
官方文档中 IoC 不提以来查找的原因是由于依赖查找在 Java EE时 代已经实现了,DI 部分实现,只不过要和 Java EE 传统容器加以区别
3.9.2 BeanFactory 和 FactoryBean 区别
BeanFactory 是 IoC 的底层容器,ApplicationContext 中通过继承 BeanFactory 接口并且在实现类中通过组合 BeanFactory 对象方式提供 BeanFactory 所有功能以及新增自己的一些功能(代理)
FactoryBean 则是创建 Bean 的一种方式,帮助实现复杂的初始化逻辑,通过 FactoryBean 创建的 Bean 是否有会包含 Bean 生命周期?后续进行讲解。
3.9.3 Spring IoC 容器启动时做了哪些准备
IoC 配置元信息读取和解析(xml、注解等读取和解析)、IoC 容器生命周期、Spring 事件发布、国际化等