框架-spring源碼分析(一)

框架-spring源碼分析(一)html

 

 參考:java

https://www.cnblogs.com/heavenyes/p/3933642.htmlnode

http://www.cnblogs.com/BINGJJFLY/p/9055454.htmlspring

https://www.cnblogs.com/leftthen/p/5440107.htmlapache

 

 

 

spring容器

1、簡介bootstrap

  spring容器是整個spring框架的核心,一般咱們說的spring容器就是bean工廠,bean工廠負責建立和初始化bean、裝配bean而且管理應用程序中的bean.spring中提供了兩個核心接口:BeanFactory和ApplicationContext,ApplicationContext是BeanFactory子接口,它提供了比BeanFactory更完善的功能.設計模式

2、ApplicationContext的工做原理緩存

  先創建一個新的java項目,搭建好spring的開發環境.而後啓動spring的容器,以下面的代碼:app

複製代碼
public class Demo {
    public static void main(String[] args) {
     ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml"); } }
複製代碼

 spring容器啓動時,會完成兩個重要的工做:加載bean的定義信息(BeanDefinition)以及初始化全部單例bean,在初始化bean的過程當中注入bean的依賴.bean的定義信息是指:bean的基本屬性,例如完整類名,是否單例等等,其實就是<bean id="" class="" scope="">元素的那些屬性.在建立bean時須要用到這些屬性,因此必需要先加載bean以及它的定義信息.框架

  先說spring容器加載bean的定義信息的實現原理,spring中有兩種配置bean的方法:

  • 使用配置文件配置bean,須要在<bean>元素中聲明bean的信息;spring容器啓動時,會讀取配置文件並進行解析,這種狀況下,只要解析bean元素就能夠獲取bean的beanName和它的定義信息.
  • 使用註解配置bean,須要在配置文件中配置bean的路徑,例如:<context:component-scan base-package="cn.spring"/>,這樣容器啓動時就會掃描cn.spring包以及子包下面的全部類,若是類上有@Controller 或者 @Service 或者@Repository或者@Component註解,spring就會加載這些類的定義信息;這裏就會有幾個問題,第一個問題是如何獲取base-package的子包以及包下的全部類?spring的作法是將包名轉化成文件系統中的路徑,而後traverse獲取該目錄下的全部.class文件,很是巧妙的一個解決方案!接下來的問題是如何從.class文件中獲取bean的定義信息呢?有兩種方式,第一種就是把經過.class文件的路徑獲取該類的包名,而後經過類加載器加載該類獲取它的定義信息,第二種方式是用asm框架從class文件中直接讀取類的定義信息。spring用的是第二種方式,我的以爲spring選擇第二種方式是有如下幾個緣由,其一,可能須要對class文件進行加強處理,也就是在class文件中增長一些新的指令,在生成代理時可能會須要這樣作;其二,反射沒法獲取類完徹底全的信息(例如:方法的參數名稱),其三,反射的性能問題;

 接下來,就是容器初始化單例bean的過程:

  spring容器在加載完全部bean的定義信息之後,會有一個refresh()操做,在refresh容器過程當中完成兩個重要的操做,第一個就是建立全部單例bean,第二個就是裝配這些建立bean(注入它們所須要的依賴);

  由於前面的操做已經加載了全部bean的定義信息,而且維護了一個<beanName,BeanDefinition>對應關係的Map,遍歷Map,就能夠取得每一個bean的定義信息,從bean的定義信息能夠知道bean是不是單例,若是是單例的,下一步就會根據bean的定義信息來決定bean實例的建立策略,若是配置了bean的factory-method,就調用factory-method建立bean實例,若是沒有配置factory-method,默認會調用bean的無參構造函數建立bean實例.

  建立bean實例以後的工做就是裝配bean,如今已經拿到了bean實例,若是bean是在配置文件中配置的,此時就會先把配置文件中配置的屬性賦值給bean實例上對應的屬性;然後由bean的後處理器(BeanPostProcessor)完成bean實例其餘屬性(經過註解配置的)的注入.若是bean是經過註解進行配置,這時直接就會由bean的後處理器完成bean的裝配.完成bean裝配的後處理器的工做原理:遍歷bean對象的字段和方法,根據字段和方法上應的註解完成相對應的注入操做.

  在裝配bean的過程當中會出現一個問題:A依賴B,裝配A的時候B的實例尚未建立,spring解決這個問題的辦法是:先建立B對象,裝配好bean,而後把B注入A,繼續完成A的裝配.

3、容器初始化過程的源碼分析

  咱們從ApplicationContext的構造函數開始,以下代碼: 

複製代碼
  /**
     * 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. --->加載全部bean的定義信息,建立全部單例bean
     * 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, ApplicationContext parent)
            throws BeansException {

        super(parent);
     // 解析給定的配置文件,完成加載全部bean的定義信息的操做 setConfigLocations(configLocations); if (refresh) {
       // refresh容器,完成建立單例bean的操做 refresh(); } }
複製代碼

  構造方法的註釋上寫的so nice.接下來,看加載bean的定義信息的過程,setConfigLocations()是在父類中實現的,接收到配置文件之後,容器開始解析配置文件.通過一系列的調用,會調用org.springframework.beans.factory.xml.XmlBeanDefinitionReader的doLoadBeanDefinitions(),到這裏終於看到Document,下面是該方法的源碼:

複製代碼
  /**
     * Actually load bean definitions from the specified XML file.
     * @param inputSource the SAX InputSource to read from
     * @param resource the resource descriptor for the XML file
     * @return the number of bean definitions found
     * @throws BeanDefinitionStoreException in case of loading or parsing errors
     */
    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {
        try {
            int validationMode = getValidationModeForResource(resource);
  // 取得Document對象  
            Document doc = this.documentLoader.loadDocument(
                    inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
 // 從Document對象中解析bean的定義信息   
            return registerBeanDefinitions(doc, resource);
        }
        catch (BeanDefinitionStoreException ex) {
            throw ex;
        }
     // ...各類異常的處理 }
複製代碼

  registerBeanDefinitions()又會通過一系列的檢查和處理,而後調用

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader的doRegisterBeanDefinitions(root)方法進行處理,這部分會從bean元素中解析出bean的定義信息,源代碼以下:
  
複製代碼
/**
     * Register each bean definition within the given root {@code <beans/>} element.
     * @throws IllegalStateException if {@code <beans profile="..."} attribute is present
     * and Environment property has not been set
     * @see #setEnvironment
     */
    protected void doRegisterBeanDefinitions(Element root) {
        String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
        if (StringUtils.hasText(profileSpec)) {
            Assert.state(this.environment != null, "environment property must not be null");
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            if (!this.environment.acceptsProfiles(specifiedProfiles)) {
                return;
            }
        }

        // any nested <beans> elements will cause recursion in this method. In
        // order to propagate and preserve <beans> default-* attributes correctly,
        // keep track of the current (parent) delegate, which may be null. Create
        // the new (child) delegate with a reference to the parent for fallback purposes,
        // then ultimately reset this.delegate back to its original (parent) reference.
        // this behavior emulates a stack of delegates without actually necessitating one.
        BeanDefinitionParserDelegate parent = this.delegate;
        this.delegate = createHelper(readerContext, root, parent);

        preProcessXml(root);
               // 重點部分,解析bean的定義信息
        parseBeanDefinitions(root, this.delegate);
        postProcessXml(root);

        this.delegate = parent;
    }    
  
  /**
     * Parse the elements at the root level in the document:
     * "import", "alias", "bean".
     * @param root the DOM root element of the document
     */
    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if (delegate.isDefaultNamespace(root)) {
            NodeList nl = root.getChildNodes();
            for (int i = 0; i < nl.getLength(); i++) {
                Node node = nl.item(i);
                if (node instanceof Element) {
                    Element ele = (Element) node;
                    if (delegate.isDefaultNamespace(ele)) {
                        parseDefaultElement(ele, delegate); // 重點:解析bean元素
                    }
                    else {
                        delegate.parseCustomElement(ele); // 重點:解析其餘元素,例如:<context<context:component-scan> or <annotation:config/>
                    }
                }
            }
        }
        else {
            delegate.parseCustomElement(root);
        }
    }
複製代碼

  到這裏,終於到了關鍵的地方,若是bean是在配置文件中配置的,由parseDefaultElement(ele, delegate)處理bean元素的解析,若是是註解配置,parseCustomElement(ele)會掃描包下的class文件,並完成解析.咱們先看配置文件中bean元素的解析方式。

複製代碼
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
            importBeanDefinitionResource(ele);
        }
        else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
            processAliasRegistration(ele);
        }
        else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
      // 重點
            processBeanDefinition(ele, delegate);
        }
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
            // recurse
            doRegisterBeanDefinitions(ele);
        }
    }

  /**
     * Process the given bean element, parsing the bean definition
     * and registering it with the registry.
     */
    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
     // 獲取bean的定義信息,用BeanDefinitionHodler對象封裝
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
            try {
                // Register the final decorated instance.---》關鍵,將bean的定義信息保存到容器
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
            }
            catch (BeanDefinitionStoreException ex) {
                getReaderContext().error("Failed to register bean definition with name '" +
                        bdHolder.getBeanName() + "'", ele, ex);
            }
            // Send registration event.
            getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }
    }
複製代碼

  接下來就是調用org.springframework.beans.factory.support.BeanDefinitionReaderUtils的registerBeanDefinition()保存bean定義信息到容器的方法了.

複製代碼
/**
     * Register the given bean definition with the given bean factory.
     * @param definitionHolder the bean definition including name and aliases
     * @param registry the bean factory to register with
     * @throws BeanDefinitionStoreException if registration failed
     */
    public static void registerBeanDefinition(
            BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
            throws BeanDefinitionStoreException {

        // Register bean definition under primary name.---》重點
        String beanName = definitionHolder.getBeanName();
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

        // Register aliases for bean name, if any.
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            for (String aliase : aliases) {
                registry.registerAlias(beanName, aliase);
            }
        }
    }
複製代碼

  ok,來看最終的保存代碼:

org.springframework.beans.factory.support.DefaultListableBeanFactory中的registerBeanDefinition();先看DefaultListableBeanFactory保存bean定義信息的Map的聲明:
  
複製代碼
    /** Map of bean definition objects, keyed by bean name */
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();

    /** List of bean definition names, in registration order */
    private final List<String> beanDefinitionNames = new ArrayList<String>();

複製代碼

  保存bean定義信息的方法:

複製代碼
  //---------------------------------------------------------------------
    // Implementation of BeanDefinitionRegistry interface
    //---------------------------------------------------------------------

    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException {

        Assert.hasText(beanName, "Bean name must not be empty");
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");

        if (beanDefinition instanceof AbstractBeanDefinition) {
            try {
                ((AbstractBeanDefinition) beanDefinition).validate();
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Validation of bean definition failed", ex);
            }
        }
    // 保存bean定義信息,線程同步
        synchronized (this.beanDefinitionMap) {
      // 判斷當前bean的定義信息是否已經保存 Object oldBeanDefinition = this.beanDefinitionMap.get(beanName); if (oldBeanDefinition != null) { if (!this.allowBeanDefinitionOverriding) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound."); } else { if (this.logger.isInfoEnabled()) { this.logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } } else {
         // 保存beanName this.beanDefinitionNames.add(beanName); this.frozenBeanDefinitionNames = null; }
       // 保存beanName和bean的定義信息到Map this.beanDefinitionMap.put(beanName, beanDefinition);      
            resetBeanDefinition(beanName);
        }
    }
複製代碼

 上面就是spring解析配置文件中的bean定義信息,而後保存beanName和bean定義信息到Map中.這個過程主要就是xml的解析.接下來咱們看spring是如何解析註解方式配置的bean.回到parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)方法,如今重點關注:delegate.parseCustomElement(ele)方法.若是咱們在配置文件用<context:component-scan  base-package="">方式來指定自動掃描的包,以後就會調用org.springframework.context.annotation.ComponentScanBeanDefinitionParser的parse().下面是parse()方法的源代碼:  

複製代碼
public BeanDefinition parse(Element element, ParserContext parserContext) {
     // 解析<context:component-scan元素,獲取base-package String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE), ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); // Actually scan for bean definitions and register them. ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
     //重點: 掃描basePackage下全部的class文件,讀取bean的定義信息 Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null; }
複製代碼

重點關注scanner.doScan(basePackges)方法,該方法完成整個核心操做--->根據包名獲取包下全部的class的定義信息.直接看org.springframework.context.annotation.ClassPathBeanDefinitionScanner的scan():注意,看源碼時必定要多關注註釋,例以下面方法上的註釋就很是有意義.

複製代碼
  /**
     * Perform a scan within the specified base packages, 
     * returning the registered bean definitions.
     * <p>This method does <i>not</i> register an annotation config processor
     * but rather leaves this up to the caller.
     * @param basePackages the packages to check for annotated classes
     * @return set of beans registered if any for tooling registration purposes (never {@code null})
     */
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Assert.notEmpty(basePackages, "At least one base package must be specified");
        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
        for (String basePackage : basePackages) { // 遍歷每個basepackages
       // 1.獲取basePackage下bean的定義信息 Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) {
         //2.根據掃描的信息,解析bean的一些定義信息 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder);
            // 3.將bean的定義信息添加到容器中 registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
複製代碼

  第1個步驟咱們核心關注點,它完成從文件系統中讀取class文件的操做,第3個步驟在以前已經說了,就是保存bean的定義信息到容器的DefaultListableBeanFactory的beanDefinitionMap 中.重點關注第1個步驟,看findCandidateComponents()的源代碼:

複製代碼
    /**
     * Scan the class path for candidate components.
     * @param basePackage the package to check for annotated classes
     * @return a corresponding Set of autodetected bean definitions
     */
    public Set<BeanDefinition> findCandidateComponents(String basePackage) {
        Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
        try {
            String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                    resolveBasePackage(basePackage) + "/" + this.resourcePattern;
       // 1.獲取包下的class文件路徑,例如E:\Program Files (x86)\MyEclipse10\workplace2\spr\bin\cn\jack\domain\User.class,
       // 每個class文件的路徑封裝成Resource對象. Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } if (resource.isReadable()) { try {
              // 2.使用asm框架讀取class文件,獲取類的定義信息 MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource); if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setResource(resource); sbd.setSource(resource); if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } else { if (debugEnabled) { logger.debug("Ignored because not a concrete top-level class: " + resource); } } } else { if (traceEnabled) { logger.trace("Ignored because not matching any filter: " + resource); } } } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to read candidate component class: " + resource, ex); } } else { if (traceEnabled) { logger.trace("Ignored because not readable: " + resource); } } } } catch (IOException ex) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); }
     //3.返回benadefinition集合 return candidates; }
複製代碼

 第1個步驟主要是解析文件路徑,而後遍歷文件夾獲取每一個class文件的地址;第2個步驟用asm框架來讀取class文件獲取類的信息封裝成BeanDefinition對象.

第2個步驟最後調用的是org.springframework.core.type.classreading.SimpleMetadataReader的構造函數,下面是該類的部分源代碼:

複製代碼
final class SimpleMetadataReader implements MetadataReader {

    private final Resource resource;
    private final ClassMetadata classMetadata;
    private final AnnotationMetadata annotationMetadata;

    SimpleMetadataReader(Resource resource, ClassLoader classLoader) throws IOException {
        InputStream is = resource.getInputStream();
        ClassReader classReader = null;
        try {
       // asm框架讀取class文件 classReader = new ClassReader(is); } finally { is.close(); }     // 採用訪問者模式來獲取class類信息 AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader); classReader.accept(visitor, true); this.annotationMetadata = visitor; // (since AnnotationMetadataReader extends ClassMetadataReadingVisitor) this.classMetadata = visitor; this.resource = resource; }
複製代碼

ClassReader是asm框架中核心類,具體用法能夠參考asm的官網.

上面說的過程就是spring容器加載bean定義信息的過程.過程很長,但實現原理卻並不複雜.

2. 初始化單例bean的過程

  上面分析了spring容器加載bean定義信息的過程,接下來分析bean的初始化以及建立bean的過程.回到ApplicationContext中的構造函數,入口爲refresh().refresh方法在父類中實現的。下面是AbstractApplicationContext類refresh()方法的源代碼:

複製代碼
public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) { // 線程同步
            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);// 容器的後處理器

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);//調用容器的後處理器

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);//註冊bean的後處理器

                // 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);// 重點,註釋寫的so nice,初始化全部單例bean

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }
        }
    }
複製代碼

後處理器是一種特殊bean,用於完成一些自身操做.

容器後處理器:對容器自己進行處理,在容器實例化其餘任何Bean以前讀取配置文件的元數據並可能修改這些數據.PropertyPlaceholderConfigurer就是一個容器後處理器,用於完成beans.xml中引入其餘配置文件中內容操做.

Bean後處理器:即當Spring容器建立完Bean實例以後對bean進行一些處理,例如:完成bean的裝配等操做。

回到refresh()方法,重點關注:finishBeanFactoryInitialization(beanFactory);這個方法會調用DefaultListableBeanFactory.preInstantiateSingletons方法.

複製代碼
public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isInfoEnabled()) {
            this.logger.info("Pre-instantiating singletons in " + this);
        }
        synchronized (this.beanDefinitionMap) { // 線程同步
            // 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<String>(this.beanDefinitionNames);
            for (String beanName : beanNames) {// 遍歷beanNames
                RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
                if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {//單例非延遲實例的bean
                    if (isFactoryBean(beanName)) { // 工廠bean.FactoryBean接口的子類
                        final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
                        boolean isEagerInit;
                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                            isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                                public Boolean run() {
                                    return ((SmartFactoryBean) factory).isEagerInit();
                                }
                            }, getAccessControlContext());
                        }
                        else {//普通bean
                            isEagerInit = (factory instanceof SmartFactoryBean &&
                                    ((SmartFactoryBean) factory).isEagerInit());
                        }
                        if (isEagerInit) {
                            getBean(beanName);
                        }
                    }
                    else {
                        getBean(beanName); // 從容器中獲取bean,若是沒有建立,並完成裝配
                    }
                }
            }
        }
    }
複製代碼

getBean(beanName)方法會調用doGetBean方法.這是個很關鍵的地方,切記註釋很重要

複製代碼
    /**
     * Return an instance, which may be shared or independent, of the specified bean.
     * @param name the name of the bean to retrieve
     * @param requiredType the required type of the bean to retrieve
     * @param args arguments to use if creating a prototype using explicit arguments to a
     * static factory method. It is invalid to use a non-null args value in any other case.
     * @param typeCheckOnly whether the instance is obtained for a type check,
     * not for actual use
     * @return an instance of the bean
     * @throws BeansException if the bean could not be created
     */
    @SuppressWarnings("unchecked")
    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已建立,調用方法返回該bean
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
       //若是是工廠bean,則返回beanFactory.getObject(),普通bean直接返回sharedInstance bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { //bean未建立 // Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory();
       // 檢查父容器是否已經建立該bean,有則從父容器獲取bean返回 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); } final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dependsOnBean : dependsOn) { getBean(dependsOnBean); registerDependentBean(dependsOnBean, beanName); } } // Create bean instance.---》建立單例bean if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory() { public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args);// ---> 建立bean的方法 } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } } });
         // 返回建立的單例bean bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { // 建立原型bean,scope="prototype" // 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 '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, new ObjectFactory() { 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) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; " + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } // Check if required type matches the type of the actual bean instance. if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) { try { return getTypeConverter().convertIfNecessary(bean, requiredType); } catch (TypeMismatchException ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to convert bean '" + name + "' to required type [" + ClassUtils.getQualifiedName(requiredType) + "]", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } }
    // 返回bean return (T) bean; }
複製代碼

createBean(beanName, mbd, args)方法會調用doCreateBean()完成bean的建立工做,源代碼以下:

複製代碼
/**
     * Actually create the specified bean. Pre-creation processing has already happened
     * at this point, e.g. checking <code>postProcessBeforeInstantiation</code> callbacks.
     * <p>Differentiates between default bean instantiation, use of a
     * factory method, and autowiring a constructor.
     * @param beanName the name of the bean
     * @param mbd the merged bean definition for the bean
     * @param args arguments to use if creating a prototype using explicit arguments to a
     * static factory method. This parameter must be <code>null</code> except in this case.
     * @return a new instance of the bean
     * @throws BeanCreationException if the bean could not be created
     * @see #instantiateBean
     * @see #instantiateUsingFactoryMethod
     * @see #autowireConstructor
     */
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
       // 1.建立bean的包裝類,裝飾設計模式 instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null); // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, new ObjectFactory() { public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); } // Initialize the bean instance. Object exposedObject = bean; try {
       //2.裝配bean populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { exposedObject = initializeBean(beanName, exposedObject, mbd); } } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); } } } } // Register bean as disposable. try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); }      //3.返回 return exposedObject; }
複製代碼

首先看第1個步驟,這個步驟中會建立bean實例和bean的包裝類,這裏使用了裝飾設計模式.建立bean的實例過程比較簡單,若是配置bean時指定了bean的建立方法 factory-method,就用factory-method建立bean實例,默認會使用無參構造函數建立bean實例.這部分重點關注裝配bean的過程.

複製代碼
/**
     * Create a new instance for the specified bean, using an appropriate instantiation strategy:
     * factory method, constructor autowiring, or simple instantiation.
     * @param beanName the name of the bean
     * @param mbd the bean definition for the bean
     * @param args arguments to use if creating a prototype using explicit arguments to a
     * static factory method. It is invalid to use a non-null args value in any other case.
     * @return BeanWrapper for the new instance
     * @see #instantiateUsingFactoryMethod
     * @see #autowireConstructor
     * @see #instantiateBean
     */
    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
        // Make sure bean class is actually resolved at this point.
        Class beanClass = resolveBeanClass(mbd, beanName);

        if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
        }

        if (mbd.getFactoryMethodName() != null)  {// 使用工廠方法建立bean,<bean factory-method="">
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }

        // Shortcut when re-creating the same bean...
        boolean resolved = false;
        boolean autowireNecessary = false;
        if (args == null) {
            synchronized (mbd.constructorArgumentLock) {
                if (mbd.resolvedConstructorOrFactoryMethod != null) {
                    resolved = true;
                    autowireNecessary = mbd.constructorArgumentsResolved;
                }
            }
        }
        if (resolved) {
            if (autowireNecessary) {
                return autowireConstructor(beanName, mbd, null, null);
            }
            else {
                return instantiateBean(beanName, mbd);
            }
        }

        // Need to determine the constructor...
        Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
            return autowireConstructor(beanName, mbd, ctors, args);
        }
    // 用默認的構造函數建立bean,反射獲取構造函數,constructor.newInstance()建立bean.
        // No special handling: simply use no-arg constructor. 
        return instantiateBean(beanName, mbd);
    }
複製代碼

  如今來看裝配bean的過程,這個過程完成注入bean的依賴對象,若是bean是在配置文件配置的,則把從xml中解析出來的屬性注入給bean實例,若是是用註解配置的依賴(@Resource 或者@AutoWired),則會解析bean的字段或者方法上的註解,根據這些註解找到對應的依賴,若是依賴對象已經建立,就直接注入依賴,不然,先建立依賴對象,在完成注入操做.

複製代碼
/**
     * Populate the bean instance in the given BeanWrapper with the property values
     * from the bean definition.
     * @param beanName the name of the bean
     * @param mbd the bean definition for the bean
     * @param bw BeanWrapper with bean instance
     */
    protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {
        PropertyValues pvs = mbd.getPropertyValues();

        if (bw == null) {
            if (!pvs.isEmpty()) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
            }
            else {
                // Skip property population phase for null instance.
                return;
            }
        }

        // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
        // state of the bean before properties are set. This can be used, for example,
        // to support styles of field injection.
        boolean continueWithPropertyPopulation = true;

        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }

        if (!continueWithPropertyPopulation) {
            return;
        }
     // 根據beanName或者type完成自動裝配
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

            // Add property values based on autowire by name if applicable.
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }

            // Add property values based on autowire by type if applicable.
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }

            pvs = newPvs;
        }

        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
     // 調用bean後處理器
        if (hasInstAwareBpps || needsDepCheck) {
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);
            if (hasInstAwareBpps) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
              // 重點:獲取bean要裝配的屬性和屬性值 pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } }      // 給bean的屬性賦值 applyPropertyValues(beanName, mbd, bw, pvs); }
複製代碼

   InstantiationAwareBeanPostProcessor是BeanPostProcessor的子接口,能在bean初始化先後對bean進行處理.InstantiationAwareBeanPostProcessor有如下幾個子類:

  

  @Resource註解注入依賴的工做就是由CommonAnnotationBeanPostProcessor完成的.下面是該類postProcessPropertyValues()的源碼:

複製代碼
public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
     //1.根據bean的字節碼,遍歷全部的字段和方法,獲取須要注入的字段或者方法
        InjectionMetadata metadata = findResourceMetadata(bean.getClass());
        try {
       //2.從容器中查找依賴對象,並賦值給相應的字段,完成bean的裝配 metadata.inject(bean, beanName, pvs); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex); } return pvs; }
複製代碼

  第1個步驟主要就是根據字節碼獲取全部字段和方法,而後遍歷查找有@Resource註解的字段或方法以及依賴bean的beanName,第2個步驟從容器中依賴對象的beanName(@Resource的name屬性值),若是容器中沒有該依賴對象就建立,有的話就直接獲取,並賦值給bean的屬性.這樣,就經過bean的後處理器完成了bean的裝配過程.

  到這裏,容器的啓動過程就完成了,此時就能夠對外提供服務了.上面就是本人對spring容器部分源碼學習的一些總結.往後,瞭解更多會不定時更新上來!

  

  

 

 

 

 

 

Spring bean是如何加載的

Spring bean是如何加載的

加載bean的主要邏輯

在AbstractBeanFactory中doGetBean對加載bean的不一樣狀況進行拆分處理,並作了部分準備工做
具體以下

  1. 獲取原始bean name
    1. 根據alia獲取原始bean name
    2. 去除FactoryBean時的& [若是是須要獲取FactoryBean自省,配置時須要在bean name前添加&]
  2. 嘗試從緩存中獲取實例
    1. 若是獲取到實例,還要委託getObjectForBeanInstance解決FactoryBean的場景,就是調用getObject
  3. 判斷原型場景的循環依賴問題,若是是原型同時bean又正在建立,說明是循環依賴,那直接拋異常,spring不嘗試解決原型的循環依賴
  4. 若是在本容器中沒有定義該bean,須要去父容器查找
    • 若是有參數,結合參數初始化
    • 若是沒有參數,須要結合類型初始化,這邊的調用是這個分支(固然這邊同樣沒有類型)
  5. 若是不是類型檢查,這邊須要標記bean正在實例化
  6. bean實例化的準備工做
    1. 合併父bean的定義,並轉化GenericBeanDefinition爲RootBeanDefinition
    2. 校驗BeanDefinition,若是是抽象類或者非原型帶參數拋異常[這邊註釋說的是隻有原型才能夠配置構造方法的參數]
    3. 解決bean的依賴
      • 註冊依賴的bean
      • 遞歸調用getBean實例化依賴bean
  7. 建立單例的實例
    • 爲解決循環依賴問題,這邊使用ObjectFactory在實例化前先暴露bean
    • 老規矩,須要委託getObejctForBeanInstance解決FactoryBean的問題
  8. 建立原型實例
    • 建立前的準備工做,使用prototypesCurrentlyInCreation標記bean正在實例化
    • 委託createBean實例化bean
    • 建立後的善後工做,從prototypesCurrentlyInCreation中刪除標記
    • 老規矩,委託getObjectForBeanInstance解決工廠方法的問題
  9. 建立其餘scope的實例,這邊的邏輯結合了單例跟原型的處理邏輯,即便用解決循環依賴的ObjectFactory也使用prototypeCreation的標記
    • 獲取做用域scope,並校驗是否已配置
    • 使用ObjectFactory提前暴露實例
    • 標記bean正在建立並委託createBean實例化
    • 又是委託getObjectForBeanInstance解決工廠方法問題
  10. 最後須要對建立的實例進行類型校驗,若是不一致,這邊還須要委託TypeConverter進行類型裝換

AbstractBeanFactory

@Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { // 獲取原始的bean name,去除&,解決alias問題 final String beanName = transformedBeanName(name); Object bean; // 嘗試從緩存中獲取bean // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { // ... } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } // 若是從緩存中或得bean,還須要判斷是不是FactoryBean,並調用getObejct bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 若是是原型scope,這邊又是正在建立,說明有循環依賴,而原型的循環依賴Spring是不解決的 // Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 若是當前容器沒有配置bean,那麼去父容器查找 // 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 { // 實例化類以前,先去容器中獲取配置的bean信息,這邊須要將以前的GenericBeanDefinition轉化爲RootBeanDefinition // 同時若是父bean的話,須要合併到子bean final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dependsOnBean : dependsOn) { if (isDependent(beanName, dependsOnBean)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'"); } // 解決依賴 registerDependentBean(dependsOnBean, beanName); getBean(dependsOnBean); } } // 建立單例的實例 // Create bean instance if (mbd.isSingleton()) { // 單例狀況下,爲解決循環依賴,在實例化以前,先新建一個ObjectFactory實例 sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw 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); } // 建立其餘scope的實例 else { String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'"); } try { // 仍是先建立ObejctFactory,只是這邊沒有處理 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) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; " + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } // 這邊須要對實例進行類型校驗,若是與requiredType不一致,須要委託TypeConverter嘗試類型轉換 // Check if required type matches the type of the actual bean instance. if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) { try { return getTypeConverter().convertIfNecessary(bean, requiredType); } catch (TypeMismatchException ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to convert bean '" + name + "' to required type [" + ClassUtils.getQualifiedName(requiredType) + "]", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }

bean實例的緩存分析

上面提到在加載bean的時候,doGetBean首先嚐試的是從緩存讀取,這邊咱們來細細分析下緩存具體是如何處理的.

這邊邏輯是定義在DefaultSingletonBeanRegistry中,它是AbstractBeanFactory的父類,主要職責是共享實例的註冊.
這邊雖然定義的是singleton,可是實際使用的時候,處理prototype,其餘scope均使用了這邊進行緩存.

這邊主要是須要理解singletonObjects,singletonFactories,earlySingletonObjects,registeredSingletons這4個變量.

singletonObjects 緩存bean name ->實例

Cache of singleton objects: bean name --> bean instance
這邊緩存的是實例

singletonFactories 緩存bean name -->ObjectFactory

Cache of singleton factories: bean name --> ObjectFactory
這邊緩存的是爲解決循環依賴而準備的ObjectFactory

earlySingletonObjects 緩存提前暴露的實例 bean name -->bean instance

Cache of early singleton objects: bean name --> bean instance
這邊緩存的也是實例,只是這邊的是爲解決循環依賴而提前暴露出來的實例,實際上是ObjectFactory

registeredSingletons 已經註冊的單例bean name

Set of registered singletons, containing the bean names in registration order
上面三個變量,任意一個添加了,這邊都會添加bean name,標記已經註冊

4個變量的關係以下:

  • singletonObjects與singletonFactories,earlySingletonObjects,是互斥的.就是一個bean若是在其中任意一個變量中就,不會存在在另外一變量中.這三個變量用於記錄一個bean的不一樣狀態.
  • 若是bean已經添加到singletonObjects中,那麼singltonFactories和earlySinletonObjects都不會考慮
  • singltonFactories中的bean 經過 ObjectFactory的getObject實例化後,添加到earlySingletonObjects

咱們從下面幾個方法,能夠清楚看懂上面4個變量的使用:
DefaultSingletonBeanRegistry

/**  * 添加實例化的bean  * Add the given singleton object to the singleton cache of this factory.  * <p>To be called for eager registration of singletons.  * @param beanName the name of the bean  * @param singletonObject the singleton object  */ protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT)); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } /**  * 爲解決單例的循環依賴,這邊註冊ObjectFactory  * Add the given singleton factory for building the specified singleton  * if necessary.  * <p>To be called for eager registration of singletons, e.g. to be able to  * resolve circular references.  * @param beanName the name of the bean  * @param singletonFactory the factory for the singleton object  */ protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(singletonFactory, "Singleton factory must not be null"); synchronized (this.singletonObjects) { if (!this.singletonObjects.containsKey(beanName)) { this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } } /**  * 清除實例  * Remove the bean with the given name from the singleton cache of this factory,  * to be able to clean up eager registration of a singleton if creation failed.  * @param beanName the name of the bean  * @see #getSingletonMutex()  */ protected void removeSingleton(String beanName) { synchronized (this.singletonObjects) { this.singletonObjects.remove(beanName); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.remove(beanName); } } /**  * 獲取實例時,調用ObejctFactory的getObject 獲取實例  * Return the (raw) singleton object registered under the given name.  * <p>Checks already instantiated singletons and also allows for an early  * reference to a currently created singleton (resolving a circular reference).  * @param beanName the name of the bean to look for  * @param allowEarlyReference whether early references should be created or not  * @return the registered singleton object, or {@code null} if none found  */ protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { 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); }

 

 

 

 

 

 

 

 

 

BeanPostProcessor Bean實例的初始化先後的自定義修改

BeanPostProcessor接口的行爲方法

複製代碼
public interface BeanPostProcessor {

    /**
     * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
     * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
     * or a custom init-method). The bean will already be populated with property values.
     * The returned bean instance may be a wrapper around the original.
     * @param bean the new bean instance
     * @param beanName the name of the bean
     * @return the bean instance to use, either the original or a wrapped one; if
     * {@code null}, no subsequent BeanPostProcessors will be invoked
     * @throws org.springframework.beans.BeansException in case of errors
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
     */
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    /**
     * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
     * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
     * or a custom init-method). The bean will already be populated with property values.
     * The returned bean instance may be a wrapper around the original.
     * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
     * instance and the objects created by the FactoryBean (as of Spring 2.0). The
     * post-processor can decide whether to apply to either the FactoryBean or created
     * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
     * <p>This callback will also be invoked after a short-circuiting triggered by a
     * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
     * in contrast to all other BeanPostProcessor callbacks.
     * @param bean the new bean instance
     * @param beanName the name of the bean
     * @return the bean instance to use, either the original or a wrapped one; if
     * {@code null}, no subsequent BeanPostProcessors will be invoked
     * @throws org.springframework.beans.BeansException in case of errors
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
     * @see org.springframework.beans.factory.FactoryBean
     */
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}
複製代碼

自定義的BeanPostProcessor

複製代碼
package com.wjz.spring;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import com.wjz.core.CustomInitializable;

public class CustomBeanPostProcessor implements BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof CustomInitializable) {
            System.out.println("before init......");
            ((CustomInitializable) bean).init();
        }
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("after init......");
        return bean;
    }

}
複製代碼

自定義的修改

複製代碼
package com.wjz.core;

public abstract interface CustomInitializable {

    abstract void init();
}
複製代碼
複製代碼
package com.wjz.core;

public class Realm implements CustomInitializable {

    public void init() {
        System.out.println("init......");
    }

}
複製代碼

關於Shiro框架對於BeanPostProcessor的使用

LifecycleBeanPostProcessor

 

複製代碼
public Object postProcessBeforeInitialization(Object object, String name) throws BeansException {
        if (object instanceof Initializable) {
            try {
                if (log.isDebugEnabled()) {
                    log.debug("Initializing bean [" + name + "]...");
                }

                ((Initializable) object).init();
            } catch (Exception e) {
                throw new FatalBeanException("Error initializing bean [" + name + "]", e);
            }
        }
        return object;
    }


    /**
     * Does nothing - merely returns the object argument immediately.
     */
    public Object postProcessAfterInitialization(Object object, String name) throws BeansException {
        // Does nothing after initialization
        return object;
    }
複製代碼
public abstract interface org.apache.shiro.util.Initializable {
  
    public abstract void init() throws org.apache.shiro.ShiroException;

}

AuthenticatingRealm

public final void init() {
        //trigger obtaining the authorization cache if possible 若是可能,觸發得到受權緩存
        getAvailableAuthenticationCache();
        onInit();
    }
相關文章
相關標籤/搜索