1.容器简介
什么是容器?
Java应用中,对象与对象之间往往存在各种复杂的依赖,对象的构建也会变得越来越复杂,如果这些对象的生命周期全部由开发人员编写的话,那么工作量将会变得无比巨大,对象的管理也会非常复杂。所以才会诞生容器的概念,容器的核心左右只有一个:Bean的管理,当我们需要使用某个 Bean 时,容器会自动帮我们创建,并在适当时销毁。外界有一个标准的名词,前者称呼为 IOC,也就是控制反转,后者称呼为 DI,也就是依赖注入。
IOC/DI
-
IOC (Inversion of Control) 控制反转: 所谓控制反转,就是当我们需要某个 Bean 时,将 Bean 的名称告知容器,由容器去创建该 Bean,而不是我们手动 new 一个,这里 Bean 创建管理的控制权都交给了容器,所以这是一种控制权的反转。其通俗点讲就是需要什么东西让别人送过来,而不是自己去拿。 -
DI (Dependency Injection) 依赖注入: 就是指当 A 里面需创建 B 时,会在创建 A的时候,自动将依赖的 B 注入进去,其 B 是被动接受注入而不是自己主动去找。换句话说就是指 A 不是从容器中查找它依赖的 B ,而是容器创建在A 的时候主动将它依赖的 B 注入给它。
2.容器的结构
容器本质上可以也可以看作是 Bean 工厂,该工厂管理 Bean 的生命周期,以及 Bean 之间的依赖关系。外界也将 Spring 容器称为 IOC 容器。当然,这里容器仅仅是 Spring 的抽象概念,代码中将其具象化为 BeanFactory 或 ApplicationContext,容器功能也由具象化的类进行处理。
2.1 BeanFactory
BeanFactory 是容器最基础的类,它定义了容器的基本功能规范:
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}
在 BeanFactory 里只对容器的基本行为作了定义,其根本不关心你的 Bean 是如何定义怎样加载的。至于工厂是怎么生产这些对象的,这个基本的接口不关心。而要知道工厂是如何产生对象的,我们就需要看具体的容器了,也就是 BeanFactory 的子类。 BeanFactory 大致的继承关系如下:
BeanFactory 体系中常用的实现类有:
ListableBeanFactory :提供容器中 bean 迭代的功能。如返回所有 Bean 的名字、容器中 Bean 的数量等。HierarchicalBeanFactory :提供父容器的访问功能,可通过 ConfigurableBeanFactory 的setParentBeanFactory 方法设置父容器。AutowireCapableBeanFactory :为 Spring 容器之外的 Bean ,也就是未交由 Spring 管理的 Bean ,提供依赖注入的功能。
以上三个是 BeanFactory 的直系亲属,这个三个直系亲属下面又派生了两个复杂的容器:
ConfigurableBeanFactory :其继承了 HierarchicalBeanFactory 和SingletonBeanRegistry 这两个接口,其提供了很多方法,如:定义类加载器、类型转化、属性编辑器、注册依赖 Bean、销毁 bean 等,且该接口被大多数的容器继承、实现。ConfigurableListableBeanFactory :这个接口继承了 ListableBeanFactory 、AutowireCapableBeanFactory 、ConfigurableBeanFactory ,自身主要提供用于分析和修改 bean 定义以及预先实例化单例 Bean 的方法。 最后是核心容器:
DefaultListableBeanFactory :它实现了以上所有的接口,在 BeanFactory 体系中可以作为一个独立的容器使用。
2.2 ApplicationContext
上面说过 ApplicationContext 是 BeanFactory 子类,它不仅包含 BeanFactory 所有功能,还对其进行了扩展,而我们喜欢将 ApplicationContext 称为应用上下文,因为容器只是它的基本功能。
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
@Nullable
String getId();
String getApplicationName();
String getDisplayName();
long getStartupDate();
@Nullable
ApplicationContext getParent();
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}
ApplicationContext 自身提供的方法非常简单,但它继承了六个接口,来扩展自身功能:
EnvironmentCapable :获取 Environment。ListableBeanFactory 、HierarchicalBeanFactory :这是 BeanFactory 体系接口,分别提供 Bean 迭代和访问父容器的功能。MessageSource :支持国际化功能。ApplicationEventPublisher :应用事件发布器,封装事件发布功能的接口。ResourcePatternResolver :该接口继承至 ResourceLoader ,作用是加载多个 Resource。ApplicationContext 同样提供了非常多的实现类,其又可细分为两大类,ConfigurableApplicationContext 和 WebApplicationContext 。
2.2.1 ConfigurableApplicationContext
该接口是比较重要的一个接口,几乎所有的应用上下文都实现了该接口。该接口在ApplicationContext 的基础上提供了配置应用上下文的能力,此外提供了生命周期的控制能力。
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
String ENVIRONMENT_BEAN_NAME = "environment";
String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";
String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
void setId(String id);
void setParent(@Nullable ApplicationContext parent);
void setEnvironment(ConfigurableEnvironment environment);
@Override
ConfigurableEnvironment getEnvironment();
void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);
void addApplicationListener(ApplicationListener<?> listener);
void addProtocolResolver(ProtocolResolver resolver);
void refresh() throws BeansException, IllegalStateException;
void registerShutdownHook();
@Override
void close();
boolean isActive();
ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
该接口下又有几个重要的实现类:
- AbstractApplicationContext:这是个抽象类,仅实现了公共的上下文特性。这个抽象类使用了模板方法设计模式,需要具体的实现类去实现这些抽象的方法。
- GenericApplicationContext:该类继承自 AbstractApplicationContext,是为通用目的设计的,它能加载各种配置文件,例如 xml,properties 等等。它的内部持有一个 DefaultListableBeanFactory 的实例,实现了
- BeanDefinitionRegistry 接口,以便允许向其应用任何 bean 的定义的读取器。
- AnnotationConfigApplicationContext:该类继承自 GenericApplicationContext,提供了注解配置(例如:@Configuration、@Component等)和类路径扫描(scan方法)的支持。
2.2.2 WebApplicationContext
该接口是专门为 Web 应用准备的,其允许从相对于 Web 根目录的路径中装载配置文件完成初始化。
public interface WebApplicationContext extends ApplicationContext {
String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
String SCOPE_REQUEST = "request";
String SCOPE_SESSION = "session";
String SCOPE_APPLICATION = "application";
String SERVLET_CONTEXT_BEAN_NAME = "servletContext";
String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";
String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";
@Nullable
ServletContext getServletContext();
}
该接口的核心实现类有:
ConfigurableWebApplicationContext :该接口同时继承了 WebApplicationContext 和 ConfigurableApplicationContext ,提供了 Web 应用上下文的可配置的能力。GenericWebApplicationContext :该类继承自 GenericApplicationContext ,实现了 ConfigurableWebApplicationContext 。XmlWebApplicationContext :该上下文是使用 Xml 配置文件的方式,不过是在 Web 环境中使用的。AnnotationConfigServletWebServerApplicationContext :该类是被 SpringBoot 扩展而来的,SpringBoot 使用的就是该上下文。
3、ApplicationContext 启动流程
@Xiao7Application(appName = "example", port = "8081", env = AppConstant.ENV_DEV)
@EnableAspectJAutoProxy
@EnableTransactionManagement
public class SpringbootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootDemoApplication.class, args);
}
}
- 2、SpringApplication的run方法
public ConfigurableApplicationContext run(String... args) {
...
ConfigurableApplicationContext context = null;
...
try {
...
context = createApplicationContext();
...
refreshContext(context);
...
}
catch (Throwable ex) {
...
}
context = createApplicationContext();
...
}
- 3、AbstractApplicationContext的refresh方法
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + ex);
}
this.destroyBeans();
this.cancelRefresh(ex);
throw ex;
} finally {
this.resetCommonCaches();
}
}
}
逐一分析:
3.1、prepareRefresh
初始化 refresh 的上下文环境,就是记录下容器的启动时间、标记已启动状态、处理配置文件中的占位符
3.2、obtainFreshBeanFactory
这一步就是创建一个DefaultListableBeanFactory ,并进行初步的初始化,将需要的组件注册进容器。这里还会有一步加载的操作:loadBeanDefinitions(beanFactory) ;
主要有两步操作:
- 使用
ClassPathBeanDefinitionScanner 去扫描指定包中的Bean,默认创建的Scanner 只会注册Component 、ManagedBean 、Named 这三种注解的Bean - 如果
includeAnnotationConfig 属性为true 的话会注册一些支持注解、事件的处理器,比如:ConfigurationClassPostProcessor 、AutowiredAnnotationBeanPostProcessor 、EventListenerMethodProcessor 、DefaultEventListenerFactory 等。
3.3、prepareBeanFactory
对 BeanFactory 进行功能增强,如设置BeanFactory 的类加载器,添加几个 BeanPostProcessor ,手动注册几个特殊的 bean ,添加一个ApplicationListenerDetector 时间派发器。
3.4、prepareBeanFactory
一个钩子方法,提供给子类扩展。
3.5、invokeBeanFactoryPostProcessors
调用已注册的 BeanFactoryPostProcessor 、BeanDefinitionRegistryPostProcessor ,其中BeanDefinitionRegistryPostProcessor 继承了BeanFactoryPostProcessor 接口。
这里会先执行BeanDefinitionRegistryPostProcessor ,然后在执行BeanFactoryPostProcessor 。并且会根据PriorityOrdered 、Ordered 优先级进行排序控制执行顺序。
两个接口的区别:
BeanDefinitionRegistryPostProcessor :使用BeanDefinitionRegistry ,可以进行Bean 的注册删除操作。
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
BeanFactoryPostProcessor :使用ConfigurableListableBeanFactory ,可以进行Bean 的创建删除操作。
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
在3.2中创建了ConfigurationClassPostProcessor 、AutowiredAnnotationBeanPostProcessor ,这两个后置处理器很关键。
ConfigurationClassPostProcessor :解析@Configuration 、ImportSelector 、ImportBeanDefinitionRegistrar 、@Import 等接口和注解。并将解析的Bean注册进容器中去。AutowiredAnnotationBeanPostProcessor :实现了InstantiationAwareBeanPostProcessor 在对象填充属性的时候会解析@Autowired 注解并inject 填充至对象属性中。
3.6-3.8、 initMessageSource、initApplicationEventMulticaster、onRefresh
初始化国际化资源、初始化事件广播器、容器刷新的钩子函数。
3.9、registerListeners
注册事件监听器:就是从已注册的Bean 中找出实现ApplicationListener 接口的Bean 添加进ApplicationEventMulticaster 中,如果有earlyApplicationEvents 容器事件的话,进行时间的派发。
3.10、finishBeanFactoryInitialization
这一步应该是整个容器刷新最重要的一步了。创建还没实例化的非懒加载的Bean 。
这一步只是创建还没实例化的Bean ,并不是说所所有Bean 的创建都在这里。Bean的创建可以在Factory 创建好之后的任何地方实例化。
以下是需要注意的要点:
-
doCreateBean 之前会给Bean 一下提前创建的机会,通过InstantiationAwareBeanPostProcessor 接口的postProcessBeforeInstantiation 方法实现。 -
createBeanInstance 使用构造方法实例化对象时会回调SmartInstantiationAwareBeanPostProcessor 的determineCandidateConstructors 方法寻找构造函数创建对象。没有才会使用默认构造函数。 -
创建完实例后会执行MergedBeanDefinitionPostProcessor 的postProcessMergedBeanDefinition 后置处理。 -
这时候有一步操作是用于借据循环依赖的问题。放入一个FactoryBean 到三级缓存中,到时候获取对象会执行SmartInstantiationAwareBeanPostProcessor 的getEarlyBeanReference 方法获取代理对象,从而实现对代理对象循环依赖的支持。这里如果只是循环依赖的话二级缓存也是足够的。 -
populateBean 填充属性,填充之前会调用InstantiationAwareBeanPostProcessor 的postProcessAfterInstantiation 后置处理。 这一步会获取对象的PropertyValues 属性值对象,会调用InstantiationAwareBeanPostProcessor 的postProcessProperties 对属性对象扩展处理。 找对对应的属性对象后会执行操作,applyPropertyValues 这里有一步操作是使用BeanDefinitionValueResolver 解析值,因为注入的属性可能是对象而不是基础类型。比如如果是RuntimeBeanReference 对象则会去容器中获取到。最后通过反射将对象的属性设置进去。 -
initializeBean 初始化对象,到了这一步,其实对象已经创建好了,只是进行一些额外的初始化操作。 invokeAwareMethods :设置aware 对象(BeanNameAware 、BeanClassLoaderAware 、BeanFactoryAware ) 执行BeanPostProcessor 的postProcessBeforeInitialization 初始化前置处理方法。 invokeInitMethods(beanName, wrappedBean, mbd) :执行自定义的初始化方法,然后执行初始化后置处理器方法。像Aop 的代理对象也就是在这一步去创建的,也有可能是getEarlyBeanReference 方法中创建的。 对象的创建到这里也已经完成了。
3.11、 finishRefresh
完成刷新过程,发布应用事件。
4、Spring中的钩子接口
4.1、Aware 接口
Aware 从字面意思理解就是知道、感知的意思,是用来获取 Spring 内部对象的接口。Aware 自身是一个顶级接口,它有一系列子接口,在一个 Bean 中实现这些子接口并重写里面的 set 方法后,Spring 容器启动时,就会回调该 set 方法,而相应的对象会通过方法参数传递进去。
BeanFactoryAware :获取 BeanFactory 对象,它是基础的容器接口。ApplicationContextAware :获取Content BeanNameAware :获取 Bean 的名称。EnvironmentAware :获取 Environment 对象,它表示整个的运行时环境,可以设置和获取配置属性。ApplicationEventPublisherAware :获取 ApplicationEventPublisher 对象,它是用来发布事件的。ResourceLoaderAware :获取 ResourceLoader 对象,它是获取资源的工具。
4.2、BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
BeanFactoryPostProcessor 是 Bean 工厂的后置处理器,一般用来修改上下文中的 BeanDefinition ,修改 Bean 的属性值。
BeanDefinitionRegistryPostProcessor 是 BeanDefinitionRegistry 的后置处理器,一般用来扩展Bean 的注册。
4.3、@Import、ImportSelector、ImportBeanDefinitionRegistrar
ImportSelector 是一个较为重要的扩展接口,通过该接口可动态的返回需要被容器管理的类,不过一般用来返回外部的配置类。可在标注 @Configuration 注解的类中,通过 @Import 导入 ImportSelector 来使用。
ImportBeanDefinitionRegistrar 和 ImportSelector 类似,也是配合 @Import 使用,不过 ImportBeanDefinitionRegistrar 更为直接一点,它可以直接把 Bean 注册到容器中。
它们是在ConfigurationClassPostProcessor 中扩展实现的,也是Spring 启动是会自动注册的几个处理器之一。
3.4、InstantiationAwareBeanPostProcessor
它是BeanPostProcessor 的子接口。 调用时机:
- 对象创建前调一次,给机会提前创建。
postProcessBeforeInstantiation - 填充属性前调用一次。
postProcessAfterInstantiation - 填充属性时调一次。
postProcessProperties
3.5、SmartInstantiationAwareBeanPostProcessor
它是InstantiationAwareBeanPostProcessor 的子接口。
predictBeanType :断言这个Bean 的所属类型。determineCandidateConstructors :获取对象的构造方法getEarlyBeanReference :提供代理扩展的,获取对象的早起引用对象。
3.6、MergedBeanDefinitionPostProcessor
它是BeanPostProcessor 的子接口。
postProcessMergedBeanDefinition :它会在对象实例化但是没填充属性值之前回调一次。resetBeanDefinition :removeBeanDefinition 时的回调通知方法做一些缓存数据的变更之类的。
5、AOP的原理分析
Java 代理博客:https://www.cnblogs.com/cenyu/p/6289209.html
AOP 也就是通过使用Spring 的扩展接口来实现对Bean 的代理的。直接看AnnotationAwareAspectJAutoProxyCreator 的组成。 扩展原理也就是BeanPostProcessor 接口了。直接看它的postProcessAfterInitialization 方法。
wrapIfNecessary 方法的逻辑:
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
具体的创建方法createProxy :
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
有街口使用JdkDynamicAopProxy 没有接口则使用CglibAopProxy ,这里只看JdkDynamicAopProxy
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
ReflectiveMethodInvocation 中的proceed 执行流程
public Object proceed() throws Throwable {
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
return proceed();
}
}
else {
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
注意这里是执行链路,因为MethodInterceptor 可以继续回调this.proceed() ,如果某个节点断了也就中断了。或者某个节点需要下面的节点执行完成后才执行,就可以先执行proceed在处理当前节点的逻辑。其实就是责任链模式。
|