脉络思路:学习Spring的两大特性IOC与AOP,都离不开容器,那么就要先了解容器是什么?如何使用?容器是对象从创建到使用,再到销毁整个流程的控制。下面梳理下创建对象过程,加载配置文件 ——> 解析——> 封装BeanDefinition对象 ——> 实例化 ——> 完整对象。。。
下面从加载配置文件入手:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd ">
<context:property-placeholder location="classpath:org/springframework/web/context/WEB-INF/myplaceholder.properties"/>
<bean id="myBean" class="org.springframework.beans.factory.access.TestBean">
<property name="name" value="${myBeanValue}"></property>
</bean>
</beans>
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.access.TestBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SimpleDemoTest {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("org/springframework/web/context/beans1.xml");
TestBean bean = (TestBean) context.getBean("mybean");
System.out.println(bean.getName());
}
}
1、加载配置文件,封装成beanDefinition对象
为了可以扩展加载更多类型的配置文件,提供一层BeanDefinitionReader接口层(让不同类型的加载Reader去实现)。加载XML配置文件,实际上用XmlBeanDefinitionReader读取配置文件,统一封装成BeanDefinition对象。
在启动过程是一个核心方法refresh(),refresh()方法实现是在AbstractApplicationContext.java中
/**
* Create a new ClassPathXmlApplicationContext with the given parent,
* loading the definitions from the given XML files.
* @param configLocations array of resource locations
* @param refresh whether to automatically refresh the context,
* loading all bean definitions and creating all singletons.
* Alternatively, call refresh manually after further configuring the context.
* @param parent the parent context
* @throws BeansException if context creation failed
* @see #refresh()
*/
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
下面对refresh()中各个方法做个简单的介绍:
@Override
public void refresh() throws BeansException, IllegalStateException {
//startupShutdownMonitor对象在spring环境刷新和销毁的时候都会用到,确保刷新和销毁不会同时执行
synchronized (this.startupShutdownMonitor) {
// 准备工作,例如记录事件,设置标志,检查环境变量等,并有留给子类扩展的位置,用来将属性加入到applicationContext中
prepareRefresh();
// 创建beanFactory,这个对象作为applicationContext的成员变量,可以被applicationContext拿来用,
// 并且解析资源(例如xml文件),取得bean的定义,放在beanFactory中
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 对beanFactory做一些设置,例如类加载器、spel解析器、指定bean的某些类型的成员变量对应某些对象等
prepareBeanFactory(beanFactory);
try {
// 子类扩展用,可以设置bean的后置处理器(bean在实例化之后这些后置处理器会执行)
postProcessBeanFactory(beanFactory);
// 执行beanFactory后置处理器(有别于bean后置处理器处理bean实例,beanFactory后置处理器处理bean定义)
invokeBeanFactoryPostProcessors(beanFactory);
// 将所有的bean的后置处理器排好序,但不会马上用,bean实例化之后会用到
registerBeanPostProcessors(beanFactory);
// 初始化国际化服务
initMessageSource();
// 创建事件广播器
initApplicationEventMulticaster();
// 空方法,留给子类自己实现的,在实例化bean之前做一些ApplicationContext相关的操作
onRefresh();
// 注册一部分特殊的事件监听器,剩下的只是准备好名字,留待bean实例化完成后再注册
registerListeners();
// 单例模式的bean的实例化、成员变量注入、初始化等工作都在此完成
finishBeanFactoryInitialization(beanFactory);
// applicationContext刷新完成后的处理,例如生命周期监听器的回调,广播通知等
finishRefresh();
}
catch (BeansException ex) {
logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);
// 刷新失败后的处理,主要是将一些保存环境信息的集合做清理
destroyBeans();
// applicationContext是否已经激活的标志,设置为false
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
跟进方法obtainFreshBeanFactory(),可以看到核心方法AbstractRefreshableApplicationContext.java中refreshBeanFactory(),创建beanFactory,同时加载全部beanDefinition对象,此时只做简单加载(其中配置占位符不会被替换,替换是在beanFactoryPostProcessor中完成)
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
//解析资源(例如xml文件),取得bean的定义,放在beanFactory中
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
2、创建beanFactory,执行后置处理器
BeanDefinition对象——>实例化,这个过程不只是new/invoke,还做了哪些操作?
BeanFactory(Interface):Spring的本质是一个bean工厂(beanFactory)或者bean容器。解决bean之间的依赖问题,达到了松耦合的效果。 在没有spring这个beanFactory之前,我们都是直接通过new来实例化各种对象,现在各种对象bean的生产都是通过beanFactory来实例化的,这样的话,spring这个beanFactory就可以在实例化bean的各个阶段进行一些额外的处理。在bean的生命周期的各个阶段对bean进行管理,并且spring将这些阶段通过各种接口暴露给我们。 我们只要让bean实现对应的接口,那么spring就会在bean的生命周期调用我们实现的接口来处理该bean。
BeanFactoryPostProcessor(Interface): BeanFactory后置处理器,是对BeanDefinition对象进行修改。
BeanPostProcessor(Interface):Bean后置处理器,是对生成的Bean对象进行修改。 (初始化中使用)
后置处理器也被抽象出来,通过实现接口类BeanFactoryPostProcessor就可以自定义创建处理器。下面加入一个MyPostProcessor
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd ">
<context:property-placeholder location="classpath:org/springframework/web/context/WEB-INF/myplaceholder.properties"/>
<bean id="myPostProcessor" class="org.springframework.MyPostProcessor"/>
<bean id="myBean" class="org.springframework.beans.factory.access.TestBean">
<property name="name" value="${myBeanValue}"></property>
</bean>
</beans>
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class MyPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("==> come to myPostProcessor ...");
}
}
控制台打印:
---------------------------------
==> come to myPostProcessor ...
this is a test
BUILD SUCCESSFUL in 32s
注解是继配置文件之后的扩展,也是在beanFactory后置处理器位置中做了处理。(同样放在后置处理器的还有,Springboot中注解自动装配功能实现方法,跟进ConfigurationClassPostProcessor中postProcessBeanDefinitionRegistry方法。可以仿照@autowire注解处理器AutowiredAnnotationBeanPostProcessor添加自定义注解,完成注解自动装配需求的实现)
/**
* Derive further bean definitions from the configuration classes in the registry.
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
}
/**
* Build and validate a configuration model based on the registry of
* {@link Configuration} classes.
*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
...
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
parser.parse(candidates);
parser.validate();
...
}
}
class ConfigurationClassParser {
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
...
processConfigurationClass(new ConfigurationClass(metadata, beanName));
...
}
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
...
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
...
}
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
// Process any @ComponentScan annotations
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), true);
// Process any @ImportResource annotations
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// Process individual @Bean methods
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
// Process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
return null;
}
}
3、对象实例化
猜测一下,通过反射的方式进行实例化代码如下(在堆空间中开启空间,属性都是默认的)
Constructor ctor = clazz.getDeclareConsturctor();
Object obj = ctor.newinstance();
下面开始验证,跟进下refresh()中 finishBeanFactoryInitialization(beanFactory)
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
beanFactory.preInstantiateSingletons()默认创建单例的对象,继续跟进。
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
...
}
去查找beanName,跟进getBean(beanName)——>doGetBean(name)——>createBean(beanName, mbd, args)——>doCreateBean(beanName, mdbToUse, args)——>createBeanInstance(beanName, mbd, args)可以看到有构造器的创建——>instantiateBean(beanName, mbd)方法——>.instantiate(mbd, beanName, parent)有在创建构造器,那么期待接下来创建实例new instance()——>BeanUtils.instantiateClass(constructorToUse)果然有new instance
Constructor<?> constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException { Assert.notNull(ctor, "Constructor must not be null"); try { ReflectionUtils.makeAccessible(ctor); if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) { return KotlinDelegate.instantiateClass(ctor, args); } else { Class<?>[] parameterTypes = ctor.getParameterTypes(); Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters"); Object[] argsWithDefaultValues = new Object[args.length]; for (int i = 0 ; i < args.length; i++) { if (args[i] == null) { Class<?> parameterType = parameterTypes[i]; argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null); } else { argsWithDefaultValues[i] = args[i]; } } return ctor.newInstance(argsWithDefaultValues); } } catch (InstantiationException ex) { throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex); } catch (IllegalAccessException ex) { throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex); } catch (IllegalArgumentException ex) { throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex); } catch (InvocationTargetException ex) { throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException()); } }
这就是实例化的老巢了...
4、对象的初始化
spring中一般分为自定义bean对象和容器容器对象,当在自定义对象中调用容器对象,可以通过aware接口去代替get/set方法。
/**
* Interface to be implemented by beans that wish to be aware of their
* owning {@link BeanFactory}.
*/
public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
/**
* Interface to be implemented by any object that wishes to be notified
* of the {@link ApplicationContext} that it runs in.
*/
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
before、after对bean进行扩展beanPostProcessor,例如:AOP动态代理有cglib和jdk两种方式,下面跟进一下BeanPostProcessor接口
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
可以找一下动态代理的实现类AbstractAutoProxyCreator,before方法直接返回bean,after方法中跟进wrapIfNecessary
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
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;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
/**
* Create an AOP proxy for the given bean.
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @param specificInterceptors the set of interceptors that is
* specific to this bean (may be empty, but not null)
* @param targetSource the TargetSource for the proxy,
* already pre-configured to access the bean
* @return the AOP proxy for the bean
* @see #buildAdvisors
*/
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());
}
init方法,执行配置文件中init-method方法
下面来找一个初始化的老巢,同之前的实例化refresh()——>finishBeanFactoryInitialization(beanFactory)——>getBean(beanName)——>doGetBean(name)——>createBean(beanName, mbd, args)——>doCreateBean(beanName, mdbToUse, args),在这个方法里,createBeanInstance(beanName, mbd, args)之后返回实例化对象,然后执行——>populateBean(beanName, mbd, instanceWrapper)填充属性和initializeBean(beanName, exposedObject, mbd)调用aware方法初始化
====================================================
梳理下容器对象的创建流程:(搞懂Refresh()里面的13个方法,后面将会细化学习)
- 创建容器 —— prepareRefresh()
- 加载配置文件,封装成 BeanDefinition —— obtainFreshBeanFactory()
- 调用 BeanFactoryPostProcessor —— invokeBeanFactoryPostProcessors(beanFactory)
- 准备工作① BeanPostProcessor —— registerBeanPostProcessors(beanFactory)
- 准备工作② 监听器、事件、广播器等 —— initApplicationEventMulticaster()、registerListeners()
- 实例化 —— finishBeanFactoryInitialization(beanFactory)
- 初始化—— finishBeanFactoryInitialization(beanFactory)
- 获取完整对象 —— finishBeanFactoryInitialization(beanFactory)