您的位置 首页 java

Java互联网架构-Spring IOC源码分析

欢迎关注头条号:java小马哥

周一至周日下午三点半!精品技术文章准时送上!!!

精品学习资料获取通道,参见文末

源码介绍之前,看几个问题:

  • Bean 的承载对象是什么?
  • Bean的定义如何存储的?
  • Bean工厂是如何生产bean的?
  • Bean的依赖关系由谁来解决?
  • Bean工厂和ApplicationContext的区别?

Bean的构建过程

spring.xml文件中保存了我们对Bean的描述配置,BeanFactory会读取这些配置然后生成对应的Bean。

这些配置信息最后由BeanDefinition来承载。

BeanDefinition(Bean定义)

IOC实现中,我们在xml中的描述的Bean信息最后都将保存至BeanDefinition对象中,其中xml bean与BeanDefinition是一对一的关系。

xml bean的属性配置与BeanDefinition对应关系

XML-Bean BeanDefinition class beanClassName scope SCOPE_SINGLETON、SCOPE_PROTOTYPE lazy-init AbstractBeanDefinition.lazyInit constructor-arg AbstractBeanDefinition.ConstructorArgument property AbstractBeanDefinition.propertyValues factory-method AbstractBeanDefinition.factoryMethondName destroy-method AbstractBeanDefinition.destroyMethodName init-method AbstractBeanDefinition.initMethodName autowire AbstractBeanDefinition.autowireMode id name BeanDefinition.java

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
 String SCOPE_SINGLETON = "singleton";
 String SCOPE_PROTOTYPE = "prototype";
 int ROLE_APPLICATION = 0;
 int ROLE_SUPPORT = 1;
 int ROLE_INFRASTRUCTURE = 2;
 ...
}
 

AbstractBeanDefinition.java

public abstract  Class  AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable {
 public static final String SCOPE_DEFAULT = "";
 public static final int AUTOWIRE_NO = 0;
 public static final int AUTOWIRE_BY_NAME = 1;
 public static final int AUTOWIRE_BY_TYPE = 2;
 public static final int AUTOWIRE_CONSTRUCTOR = 3;
 /** @deprecated */ @Deprecated
 public static final int AUTOWIRE_AUTODETECT = 4;
 public static final int DEPENDENCY_CHECK_NONE = 0;
 public static final int DEPENDENCY_CHECK_OBJECTS = 1;
 public static final int DEPENDENCY_CHECK_SIMPLE = 2;
 public static final int DEPENDENCY_CHECK_ALL = 3;
 public static final String INFER_METHOD = "(inferred)";
 private volatile Object beanClass;
 private String scope;
 private boolean abstractFlag;
 private boolean lazyInit;
 private int autowireMode;
 private int dependencyCheck;
 private String[] dependsOn;
 private boolean autowireCandidate;
 private boolean primary;
 private final Map<String, AutowireCandidateQualifier> qualifiers;
 private boolean nonPublicAccessAllowed;
 private boolean lenientConstructorResolution;
 private String factoryBeanName;
 private String  factory MethodName;
 private ConstructorArgumentValues constructorArgumentValues;
 private MutablePropertyValues propertyValues;
 private MethodOverrides methodOverrides;
 private String initMethodName;
 private String destroyMethodName;
 private boolean enforceInitMethod;
 private boolean enforceDestroyMethod;
 private boolean synthetic;
 private int role;
 private String description;
 private Resource  Resource ;
 ...
}
 

BeanDefinition registry (Bean注册器)

在上面没有看到xml bean中的id、name属性对应在bean定义中,原因是id其作为当前bean的存储key注册到BeanDefinitionRegistry注册器中。name作为别名key注册到AliasRegistry注册中心。其最后都是指向对象的BeanDefinition。

BeanDefinitionRegistry.java

public interface BeanDefinitionRegistry extends AliasRegistry {
 void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;
 void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
 BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
 boolean containsBeanDefinition(String var1);
 String[] getBeanDefinitionNames();
 int getBeanDefinitionCount();
 boolean isBeanNameInUse(String var1);
}
 

AliasRegistry.java

public interface AliasRegistry {
 void registerAlias(String var1, String var2);
 void removeAlias(String var1);
 boolean isAlias(String var1);
 String[] getAliases(String var1);
}
 

BeanDefinitionReader(Bean定义读取)

前面知道了BeanDefinition存储了xml bean信息,而BeanDefinitionRegistry基于id和name保存bean的定义,下面是xml bean到BeanDefinition然后注册到BeanDefinitionRegistry整个过程。

分为3步:

1、BeanDefinitionReader读取spring.xml

2、读取后创建BeanDefinition

3、创建好后注册到BeanDefinitionRegister

BeanDefinitionReader.java

public interface BeanDefinitionReader {
 //获取注册器
 BeanDefinitionRegistry getRegistry();
 //获取资源装载器
 ResourceLoader getResourceLoader();
 //获取bean类加载器
 ClassLoader getBeanClassLoader();
 BeanNameGenerator getBeanNameGenerator();
 //基于资源装载Bean定义并注册到注册器
 int loadBeanDefinitions(Resource var1) throws BeanDefinitionStoreException;
 
 int loadBeanDefinitions(Resource... var1) throws BeanDefinitionStoreException;
 //基于资源路径装载Bean定义并注册到注册器
 int loadBeanDefinitions(String var1) throws BeanDefinitionStoreException;
 int loadBeanDefinitions(String... var1) throws BeanDefinitionStoreException;
}
 

装载过程demo

package com.demo.spring;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import java.util.Arrays;
/**
 * com.demo.spring
 *
 * @author Zyy
 * @date 2019/2/13 11:34
 */public class BeanDefinitionReaderTest {
 public static void main(String[] args) {
 //创建一个简单注册器
 BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
 //创建bean定义读取器
 BeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
 //创建资源读取器
 DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
 //获取资源
 Resource resource = resourceLoader.getResource("spring.xml");
 //装载类定义
 reader.loadBeanDefinitions(resource);
 //打印构建bean名称
 System.out.println(Arrays.toString(registry.getBeanDefinitionNames()));
 }
}
 

运行结果

[di, driver, com.demo.spring.HelloSpring#0, com.demo.spring.LookUpTest#0, helloSpring, com.demo.spring.DI#1, com.demo.spring.DI#0, helloByName]
 

如果未给bean设置id则:class+#+索引,来标识id

com.demo.spring.HelloSpring#0
 

打印一下bean定义信息

spring.xml

 <bean id="di" name="di2" lazy-init="false" class="com.demo.spring.DI" scope="singleton" init-method="init" destroy-method="destroy"/>
 

打印语句:

System.out.println(registry.getBeanDefinition("di"));
System.out.println(registry.getAliases("di2"));
 

结果信息:

Generic bean: class [com.demo.spring.DI]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=init; destroyMethodName=destroy; defined in class path resource [spring.xml]
[Ljava.lang.String;@73a28541
 

BeanFactory(bean工厂)

有了Bean的定义,则下面可以用BeanFactory来进行构建bean。

BeanFactory.java

public interface BeanFactory {
 String FACTORY_BEAN_PREFIX = "&";
 //基于id或name获取一个bean
 Object getBean(String name) throws BeansException;
 //基于bean的类别获取bean(如果出现多个该类的实例,则会报错)但是可以指定primary="true"调整优先级来解决该报错
 <T> T getBean(String name, Class<T> requiredType) throws BeansException;
 
 <T> T getBean(Class<T> requiredType) throws BeansException;
 //基于名词获取一个bean,并覆盖默认的构造参数
 Object getBean(String name, Object... args) 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;
 //指定bean与指定class是否匹配
 boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
 boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
 Class<?> getType(String name) throws NoSuchBeanDefinitionException;
 String[] getAliases(String name);
}
 

测试demo如下:

package com.demo.spring;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.DefaultResourceLoader;
/**
 * com.demo.spring
 *
 * @author Zyy
 * @date 2019/2/13 12:19
 */public class BeanFactoryTest {
 public static void main(String[] args) {
 //注册中心
 DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
 //读取器
 XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
 //设置资源加载器
 reader.setResourceLoader(new DefaultResourceLoader());
 //装载构建bean的定义
 reader.loadBeanDefinitions("spring.xml");
 //打印
 System.out.println(beanFactory.getBean("di"));
 System.out.println(beanFactory.getBean("di2"));
 }
}
 

当getBean时,看下堆栈信息,如下

 at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:142)
 at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1147)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1099)
 at  org .springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
 at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
 at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
 - locked <0x593> (a java.util.concurrent.ConcurrentHashMap)
 at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
 at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
 at com.demo.spring.BeanFactoryTest.main(BeanFactoryTest.java:25)
 

看具体调用方法

instantiateClass:142, BeanUtils (org.springframework.beans)
instantiate:89, SimpleInstantiationStrategy (org.springframework.beans.factory.support)
instantiateBean:1147, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBeanInstance:1099, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:513, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:483, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
getObject:306, AbstractBeanFactory$1 (org.springframework.beans.factory.support)
getSingleton:230, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:302, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:197, AbstractBeanFactory (org.springframework.beans.factory.support)
main:25, BeanFactoryTest (com.demo.spring)
 

逐个点进去查看

org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
@Override
public Object getBean(String name) throws BeansException {
 return doGetBean(name, null, null, false);
}
 

AbstractBeanFactory#getBean中继续调用doGetBean,查看doGetBean,由于其中代码太多,删除检查判断,只保留核心代码

org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
protected <T> T doGetBean(
 final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
 throws BeansException {
 final String beanName = transformedBeanName(name);
 Object bean;
 // Eagerly check singleton cache for manually registered singletons.
 //从单例 缓存 中获取
 Object sharedInstance = getSingleton(beanName);
 if (sharedInstance != null && args == null) {
 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
 } else {
 
 // Check if bean definition exists in this factory.
 //从父类工厂中获取
 BeanFactory parentBeanFactory = getParentBeanFactory();
 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
 // Not found -> check parent.
 String nameToLookup = originalBeanName(name);
 if (args != null) {
 // Delegation to parent with explicit args.
 return (T) parentBeanFactory.getBean(nameToLookup, args);
 }
 else {
 // No args -> delegate to standard getBean method.
 return parentBeanFactory.getBean(nameToLookup, requiredType);
 }
 }
 if (!typeCheckOnly) {
 markBeanAsCreated(beanName);
 }
 try {
 
 // Create bean instance.
 //mbd -> RootBeanDefinition
 //判断是否单例
 if (mbd.isSingleton()) {
 sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
 @Override
 public Object getObject() throws BeansException {
 try {
 return createBean(beanName, mbd, args);
 }
 catch (BeansException ex) {
 ...
 }
 }
 });
 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
 } else if (mbd.isPrototype()) {
 // It's a prototype -> create a new instance.
 Object prototypeInstance = null;
 try {
 beforePrototypeCreation(beanName);
 prototypeInstance = createBean(beanName, mbd, args);
 }
 finally {
 afterPrototypeCreation(beanName);
 }
 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
 }
 else {
 String scopeName = mbd.getScope();
 final Scope scope = this.scopes.get(scopeName);
 if (scope == null) {
 throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
 }
 try {
 Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
 @Override
 public Object getObject() throws BeansException {
 beforePrototypeCreation(beanName);
 try {
 return createBean(beanName, mbd, args);
 }
 finally {
 afterPrototypeCreation(beanName);
 }
 }
 });
 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
 }
 catch (IllegalStateException ex) {
 ...
 }
 }
 }
 catch (BeansException ex) {
 ...
 }
 }
 return (T) bean;
}
 

其中

Object sharedInstance = getSingleton(beanName);
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
 Object singletonObject = this.singletonObjects.get(beanName);
 //如果取到的为null且判断是正在创建
 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
 //则锁住map
 synchronized (this.singletonObjects) {
 //从正在创建的earlySingletonObjects这个map中去取
 singletonObject = this.earlySingletonObjects.get(beanName);
 //如果还是取不到
 if (singletonObject == null && allowEarlyReference) {
 //从工厂获取
 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
 //如果获取到
 if (singletonFactory != null) {
 singletonObject = singletonFactory.getObject();
 //获取到则放到缓存中
 this.earlySingletonObjects.put(beanName, singletonObject);
 //从工厂中移除
 this.singletonFactories.remove(beanName);
 }
 }
 }
 }
 return (singletonObject != NULL_OBJECT ? singletonObject : null);
 }
 

其中singletonObjects、earlySingletonObjects、singletonFactories均是一个map

private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
 

对于其中的

bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
 return beanInstance;
 }
 

其中如果是FactoryBean,则调用getObject()来获取我们自定义的bean,例如

<!-- FactoryBean创建 自定义创建bean-->
<bean id="driver" class="com.demo.spring.DriverFactoryBean" >
 <property name="jdbcUrl" value="jdbc:mysql://192.168.5.104:3306"></property>
</bean>
 

其中返回的不是DriverFactoryBean,而是返回Driver

public Class<?> getObjectType() {
 return Driver.class;
}
 

总结:

1、调用BeanFactory.getBean()会触发Bean的 实例化

2、DefaultSingletonBeanRegistry中缓存了单例Bean。

3、Bean的创建于初始化是由AbstractAutowireCapableBeanFactory完成的。

另外:

IOC容器只存放单例Bean,IOC容器在初始化的时候,会将所以Bean初始化在singletonObjects这个ConcurrentHashMap中。

在获取bean的时候,首先会去singletonObjects中去取,如果scope是单例则可以获取bean,如果是多例,则取不到bean,需要从mergedBeanDefinitions这个ConcurrentHashMap中获取RootBeanDefinition,这个里面包含bean的基础信息,然后判断scope是prototype(多例),则每次都会创建一个新的实例。

对于@Autowire、@Resource等注解,在启动SpringIOC容器时,容器会装载一个AutowiredAnnotationBeanPostProcessor 后置处理器,当容易扫描到@Autowire、@Resource等注解时,就会在IOC容器中自动查找需要的Bean,并装配给该对象的属性,在使用@Autowire时,首先在容器中查询对应类型的bean,如果查询不止一个,则根据名称来查,如果名称没有则抛异常,可以将required=false来解决,如果正好查询到一个,则就将该bean装配给@Autowire指定的变量。

对于bean之间相互引用的情况,比如A依赖B,B依赖A,这种情况时,先去实例化A,然后发现依赖B,接着去实例化B,如果此时发现B依赖A,容器会获取A的一个早期引用(early reference),将这个早期引用的A注入给B,然后B实例化完了,则实例化A也就完成了。当然对于这种循环引用的代码应该规避,这种不是正常的场景。

涉及的类:

BeanDefinition

DefaultResourceLoader

XmlBeanDefinitionReader

BeanDefinitionRegistry

BeanFactory

DefaultListableBeanFactory

AutowireCapableBeanFactory

AbstractAutowireCapableBeanFactory

SingletonBeanRegistry

DefaultSingletonBeanRegistry

整个流程:

run->getBean->BeanFactory->doGetBean->AbstructBeanFactory
->getSingleton(从缓存中获取,如果是单例,为空则创建并缓存,如果是多例则直接创建)
->DefaultSingleonBeanRegistry->createBean->AbstractAutowireCapableBeanFactory
->createBeanInstance->newInstance->Constructor->反射实例化Bean
 

BeanFactory 与 ApplicationContext区别

看下结构图

ApplicationContext.java

ApplicationContext.png

从图中可以看到ApplicationContext是由BeanFactory接口派生出来的,具有BeanFactory所以功能。除此之外,还具有以下功能:

1、MessageSource,提供国际化的消息访问

2、资源访问,入url和文件

3、事件传播,实现了ApplicationListener接口的bean

4、载入多个上下文(有继承关系),使每个上下文都专注于一个特定的层次,比如应用web层

类似的

DefaultListableBeanFactory.java

封面图源网络,侵权删除)

如有收获,请帮忙转发,您的鼓励是作者最大的动力,谢谢!

一大波微服务、分布式、高并发、高可用的原创系列文章正在路上,

欢迎关注头条号:java小马哥

周一至周日早九点半!下午三点半!精品技术文章准时送上!!!

十余年BAT架构经验倾囊相授

文章来源:智云一二三科技

文章标题:Java互联网架构-Spring IOC源码分析

文章地址:https://www.zhihuclub.com/195395.shtml

关于作者: 智云科技

热门文章

网站地图