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 qualifiers; private boolean nonPublicAccessAllowed; private boolean lenientConstructorResolution; private String factoryBeanName; private String factoryMethodName; 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; ...}BeanDefinitionRegistry(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
打印語句:
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;@73a28541BeanFactory(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 getBean(String name, Class requiredType) throws BeansException; T getBean(Class requiredType) throws BeansException; //基于名詞獲取一個bean,并覆蓋默認的構造參數 Object getBean(String name, Object... args) throws BeansException; T getBean(Class 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)@Overridepublic Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false);}AbstractBeanFactory#getBean中繼續調用doGetBean,查看doGetBean,由于其中代碼太多,刪除檢查判斷,只保留核心代碼
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBeanprotected T doGetBean( final String name, final Class 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() { @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() { @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 singletonObjects = new ConcurrentHashMap(256);private final Map earlySingletonObjects = new HashMap(16);private final Map> singletonFactories = new HashMap>(16);對于其中的
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstanceif (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; }其中如果是FactoryBean,則調用getObject()來獲取我們自定義的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->反射實例化BeanBeanFactory 與 ApplicationContext區別
看下結構圖
ApplicationContext.java
ApplicationContext.png
從圖中可以看到ApplicationContext是由BeanFactory接口派生出來的,具有BeanFactory所以功能。除此之外,還具有以下功能:
1、MessageSource,提供國際化的消息訪問
2、資源訪問,入url和文件
3、事件傳播,實現了ApplicationListener接口的bean
4、載入多個上下文(有繼承關系),使每個上下文都專注于一個特定的層次,比如應用web層
類似的
DefaultListableBeanFactory.java
封面圖源網絡,侵權刪除)
如有收獲,請幫忙轉發,您的鼓勵是作者最大的動力,謝謝!
一大波微服務、分布式、高并發、高可用的原創系列文章正在路上,
歡迎關注頭條號:java小馬哥
周一至周日早九點半!下午三點半!精品技術文章準時送上!!!
十余年BAT架構經驗傾囊相授
總結
以上是生活随笔為你收集整理的java获取当前周一_Java互联网架构-Spring IOC源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: md5算出来不一样_天天吃味精,您知道是
- 下一篇: 和nptf螺纹一样吗_摩托车火花塞长短不