spring5源码阅读2spring容器启动
2021/5/9 20:31:44
本文主要是介绍spring5源码阅读2spring容器启动,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
spring5源码阅读2spring容器启动
- 1 webApp启动加载
- 2 ContextLoaderListener监听webApp启动
- 3 ContextLoader监听加载spring容器
- 4 AbstractApplicationContext刷新容器
- 4.0 prepareRefresh
- 4.1 obtainFreshBeanFactory
- 4.1.1 创建beanFactory
- 4.1.2 装载beanDefinitions
- 4.1.2.1 装载默认的beanDefinitions
- 4.1.2.1 装载自定义的beanDefinitions
- 4.1.2.1.1 PropertyPlaceholderBeanDefinitionParser
- 4.1.2.1.2 ConfigBeanDefinitionParser
- 4.1.2.1.2 TxAdviceBeanDefinitionParser
- 4.2 prepareBeanFactory
- 4.3 postProcessBeanFactory
- 4.4 invokeBeanFactoryPostProcessors 创建processor
- 4.4.1 MapperScannerConfigurer
- 4.4.1 ConfigurationClassPostProcessor
- 4.5 registerBeanPostProcessors
- 4.6 initMessageSource
- 4.7 initApplicationEventMulticaster
- 4.8 onRefresh
- 4.9 registerListeners
- 4.10 finishBeanFactoryInitialization 创建bean
- 4.10.1 preInstantiateSingletons
- 4.10.2 getBean
- 4.10.3 getSingleton
- 4.10.4 doCreateBean
- 4.10.5 getObjectForBeanInstance
- 4.5 finishRefresh
容器的启动主要是,创建容器,初始化容器,读取spring的配置文件,生成BeanDefinition,根据BeanDefinition,通过反射创建bean的实例。
1 webApp启动加载
webApp启动过程主要为加载web.xml
web.xml的加载会去加载我们配置的spring容器和springMVC容器
<!-- 启动spring的容器 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
2 ContextLoaderListener监听webApp启动
通过org.springframework.web.context.ContextLoaderListener监听webapp启动时,启动会调用org.springframework.web.context.ContextLoader#contextInitialized初始化spring容器
/** * Initialize the root web application context. */ @Override public void contextInitialized(ServletContextEvent event) { initWebApplicationContext(event.getServletContext()); }
3 ContextLoader监听加载spring容器
- 调用createWebApplicationContext,根据sevletContext配置决定使用哪种spring容器,没有配置使用默认值org.springframework.web.context.support.XmlWebApplicationContext
- 创建spring容器对象。
- 设置spring容器的父容器默认情况设置值为null
- 调用configureAndRefreshWebApplicationContext配置并刷新spring容器
- configureAndRefreshWebApplicationContext 方法
设置id
设置ServletContext(也就是ApplicationContext)
设置从ServletContext中找到要加载的spring配置文件
设置env
根据ServletContext(也就是ApplicationContext)自定义话配置spring容器
调用spring容器的org.springframework.context.support.AbstractApplicationContext.refresh()方法刷新spring容器
// Store context in local instance variable, to guarantee that // it is available on ServletContext shutdown. if (this.context == null) { this.context = createWebApplicationContext(servletContext); } if (this.context instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context; if (!cwac.isActive()) { // The context has not yet been refreshed -> provide services such as // setting the parent context, setting the application context id, etc if (cwac.getParent() == null) { // The context instance was injected without an explicit parent -> // determine parent for root web application context, if any. ApplicationContext parent = loadParentContext(servletContext); cwac.setParent(parent); } configureAndRefreshWebApplicationContext(cwac, servletContext); } }
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) { if (ObjectUtils.identityToString(wac).equals(wac.getId())) { // The application context id is still set to its original default value // -> assign a more useful id based on available information String idParam = sc.getInitParameter(CONTEXT_ID_PARAM); if (idParam != null) { wac.setId(idParam); } else { // Generate default id... wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath())); } } wac.setServletContext(sc); String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM); if (configLocationParam != null) { wac.setConfigLocation(configLocationParam); } // The wac environment's #initPropertySources will be called in any case when the context // is refreshed; do it eagerly here to ensure servlet property sources are in place for // use in any post-processing or initialization that occurs below prior to #refresh ConfigurableEnvironment env = wac.getEnvironment(); if (env instanceof ConfigurableWebEnvironment) { ((ConfigurableWebEnvironment) env).initPropertySources(sc, null); } customizeContext(sc, wac); wac.refresh(); }
4 AbstractApplicationContext刷新容器
- prepareRefresh,初始化属性,验证必要属性,并创建earlyApplicationListeners和earlyApplicationEvents。
- obtainFreshBeanFactory,创建beanFactory(DefaultListableBeanFactory),加载,解析spring的配置文件,并产生
@Override 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); // 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); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }
4.0 prepareRefresh
初始化属性,验证必要属性,并创建earlyApplicationListeners和earlyApplicationEvents。
protected void prepareRefresh() { // Switch to active. this.startupDate = System.currentTimeMillis(); this.closed.set(false); this.active.set(true); if (logger.isDebugEnabled()) { if (logger.isTraceEnabled()) { logger.trace("Refreshing " + this); } else { logger.debug("Refreshing " + getDisplayName()); } } // Initialize any placeholder property sources in the context environment. initPropertySources(); // Validate that all properties marked as required are resolvable: // see ConfigurablePropertyResolver#setRequiredProperties getEnvironment().validateRequiredProperties(); // Store pre-refresh ApplicationListeners... if (this.earlyApplicationListeners == null) { this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); } else { // Reset local application listeners to pre-refresh state. this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } // Allow for the collection of early ApplicationEvents, // to be published once the multicaster is available... this.earlyApplicationEvents = new LinkedHashSet<>(); }
4.1 obtainFreshBeanFactory
主要有创建和获取beanFactory的功能。重点在refreshBeanFactory中。
/** * Tell the subclass to refresh the internal bean factory. * @return the fresh BeanFactory instance * @see #refreshBeanFactory() * @see #getBeanFactory() */ protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); return getBeanFactory(); }
/** * This implementation performs an actual refresh of this context's underlying * bean factory, shutting down the previous bean factory (if any) and * initializing a fresh bean factory for the next phase of the context's lifecycle. */ @Override protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); this.beanFactory = beanFactory; } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
4.1.1 创建beanFactory
- 如果已经有了beanfactory则会调用destroyBeans和closeBeanFactory销毁创建的bean并且关闭beanFactory。
- 调用createBeanFactory创建beanFactory,默认创建org.springframework.context.support.DefaultListableBeanFactory为spring的核心容器
- 调用customizeBeanFactory可以自定义allowBeanDefinitionOverriding和allowCircularReferences两个字段
/** * This implementation performs an actual refresh of this context's underlying * bean factory, shutting down the previous bean factory (if any) and * initializing a fresh bean factory for the next phase of the context's lifecycle. */ @Override protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); this.beanFactory = beanFactory; } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
4.1.2 装载beanDefinitions
创建并设置beanDefinitionReader。比如环境,resourceLoader和EntityResolver为ResourceEntityResolver。
调用loadBeanDefinitions真正装载bean的定义。
该方法会获取spring配置文件的位置,然后调用beanDefinitionReader的loadBeanDefinitions方法读入所有定义在配置文件中的loadBeanDefinitions。
首先会根据web.xml中配置的spring配置文件的位置,调用resourcePatternResolver找到配置文件的确切位置,并加载成ClassPathResource。
然后调用org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(InputSource, Resource)把resource解析成(这里最终会调用tomcat解析器)dom,并注册dom中的BeanDefinition,这里会加载xsd文件。
注册BeanDefinition的时候最终会调用org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element)注册bean,这里内部会调用到parseDefaultElement。和 parseCustomElement
/** * Loads the bean definitions via an XmlBeanDefinitionReader. * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader * @see #initBeanDefinitionReader * @see #loadBeanDefinitions */ @Override protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // Configure the bean definition reader with this context's // resource loading environment. beanDefinitionReader.setEnvironment(getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // Allow a subclass to provide custom initialization of the reader, // then proceed with actually loading the bean definitions. initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); }
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException { String[] configLocations = getConfigLocations(); if (configLocations != null) { for (String configLocation : configLocations) { reader.loadBeanDefinitions(configLocation); } } }
@Override public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException { return loadBeanDefinitions(location, null); }
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException { ResourceLoader resourceLoader = getResourceLoader(); if (resourceLoader == null) { throw new BeanDefinitionStoreException( "Cannot load bean definitions from location [" + location + "]: no ResourceLoader available"); } if (resourceLoader instanceof ResourcePatternResolver) { // Resource pattern matching available. try { Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location); int count = loadBeanDefinitions(resources); if (actualResources != null) { Collections.addAll(actualResources, resources); } if (logger.isTraceEnabled()) { logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]"); } return count; } catch (IOException ex) { throw new BeanDefinitionStoreException( "Could not resolve bean definition resource pattern [" + location + "]", ex); } } else { // Can only load single resources by absolute URL. Resource resource = resourceLoader.getResource(location); int count = loadBeanDefinitions(resource); if (actualResources != null) { actualResources.add(resource); } if (logger.isTraceEnabled()) { logger.trace("Loaded " + count + " bean definitions from location [" + location + "]"); } return count; } }
@Override public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException { Assert.notNull(resources, "Resource array must not be null"); int count = 0; for (Resource resource : resources) { count += loadBeanDefinitions(resource); } return count; }
@Override public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { return loadBeanDefinitions(new EncodedResource(resource)); }
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { Assert.notNull(encodedResource, "EncodedResource must not be null"); if (logger.isTraceEnabled()) { logger.trace("Loading XML bean definitions from " + encodedResource); } Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get(); if (!currentResources.add(encodedResource)) { throw new BeanDefinitionStoreException( "Detected cyclic loading of " + encodedResource + " - check your import definitions!"); } try (InputStream inputStream = encodedResource.getResource().getInputStream()) { InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } catch (IOException ex) { throw new BeanDefinitionStoreException( "IOException parsing XML document from " + encodedResource.getResource(), ex); } finally { currentResources.remove(encodedResource); if (currentResources.isEmpty()) { this.resourcesCurrentlyBeingLoaded.remove(); } } }
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; }
@Override public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; doRegisterBeanDefinitions(doc.getDocumentElement()); }
/** * Register each bean definition within the given root {@code <beans/>} element. */ @SuppressWarnings("deprecation") // for Environment.acceptsProfiles(String...) protected void doRegisterBeanDefinitions(Element root) { // 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 = createDelegate(getReaderContext(), root, parent); if (this.delegate.isDefaultNamespace(root)) { String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); // We cannot use Profiles.of(...) since profile expressions are not supported // in XML config. See SPR-12458 for details. if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { if (logger.isDebugEnabled()) { logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + getReaderContext().getResource()); } return; } } } preProcessXml(root); parseBeanDefinitions(root, this.delegate); postProcessXml(root); this.delegate = parent; }
/** * Register each bean definition within the given root {@code <beans/>} element. */ @SuppressWarnings("deprecation") // for Environment.acceptsProfiles(String...) protected void doRegisterBeanDefinitions(Element root) { // 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 = createDelegate(getReaderContext(), root, parent); if (this.delegate.isDefaultNamespace(root)) { String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); // We cannot use Profiles.of(...) since profile expressions are not supported // in XML config. See SPR-12458 for details. if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { if (logger.isDebugEnabled()) { logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + getReaderContext().getResource()); } return; } } } preProcessXml(root); parseBeanDefinitions(root, this.delegate); postProcessXml(root); this.delegate = parent; }
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); } else { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
4.1.2.1 装载默认的beanDefinitions
这里主要看processBeanDefinition。 其实这个过程已经算是包含了processAliasRegistration和doRegisterBeanDefinitions了。
会先委托给其他进行解析,最终调用org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseBeanDefinitionElement(Element, BeanDefinition)解析bean的定义 获取元素的id和和name属性 如果name属性不为空,则会把name加入到alias中。 如果没有id,且含有name。就会把name当做id来处理,并把name从alias中移除。 如果containingBean等于null意味着需要新增BeanDefinition,需要验证name的唯一性,使用过的名称放在usedNames中,如果name没有被使用过,就会把name和alias放入到usedNames 调用parseBeanDefinitionElement,解析bean的id。 把bean的id放入到parseState中。 获取bean的className 获取bean的父bean 根据bean的父bean和className创建BeanDefinition,这里BeanDefinition的类是:org.springframework.beans.factory.support.GenericBeanDefinition 调用parseBeanDefinitionAttributes解析BeanDefinition的属性: 如果有singleton打印错误 设置scope 设置scope为父bean的scope如果父bean存在 设置abstract 设置lazy-init 设置autowire 设置depends-on 设置autowire-candidate 设置primary 设置init-method 设置destroy-method 设置factory-method 设置factory-bean 设置description 调用parseMetaElements解析元素的meta,这个meta我还没有用过,从解析的代码来看,是个key-value的标签。 调用parseLookupOverrideSubElements解析元素的lookup-method,这个我也没有用过,从解析的代码来看,一个是方法的名称,一个引用的bean的id。 调用parseReplacedMethodSubElements解析元素的replaced-method,这个我也没有用过,从解析的代码来看,一个是方法的名称,一个引用的bean的id,可以实现更加精细的控制。 调用parseConstructorArgElements解析所有的构造参数。这个曾经也算是一个比较经典的构造办法。只是现在用的越来越少了。本次案例中没有使用构造,所以只是粗略的看下。 最终会调用parseConstructorArgElement解析每一个constructor-arg 内部会先获得index,type, name 属性 如果有index 先验证index > 0 创建ConstructorArgumentEntry对象,并放入parseState里面 调用parsePropertyValue解析property的值 可以看到只允许有ref,value,子元素(map,list,array,自定义元素)中的一种 如果是ref,则会创建ref(RuntimeBeanReference的实例),并设置ref的source为当前的constructor-arg,默认情况啥也不做。然后返回ref 如果是value,则会创建valueHolder(TypedStringValue的实例),并设置valueHolder的source为当前的constructor-arg,默认情况啥也不做。然后返回valueHolder 如果是map或者list,调用parsePropertySubElement进行解析 在解析子元素时,会先看命名空间是不是默认的,不是默认的会调用parseCustomElement进行解析。 如果是bean元素则调用parseBeanDefinitionElement进行解析,并返回bean,如果需要装饰,然后调用decorateBeanDefinitionIfRequired进行装饰。装饰时,会先找到装饰器,再去装饰,aop就用了装饰,我们在aop里面在看。 如果是ref元素则会类似上面的ref,明显多了一个父bean的处理。 如果是idref元素类似ref处理 如果是value则调用parseValueElement进行处理。会先获取value值,然后type属性,如果没有设置type为默认值,最后根据value和type调用buildTypedStringValue构造typedValue(TypedStringValue的实例),并设置source和specifiedTypeName 其他类似的有:array,list,set,map,props,这个不细写了,set,map,验证比较多,props的是key-value形式的。 其他元素抛出异常。 其他情况抛出异常 根据上面解析到的value创建valueHolder为ConstructorArgumentValues.ValueHolder的实例 设置type 设置name 设置source 判断当前contructor有没有,当前的index,如果有设置index的参数的值为valueHolder 从parseState里面取出ConstructorArgumentEntry对象 如果没有index 大致情况类似于index的情情况 调用parsePropertyElements解析property请参考上面的parsePropertyValue 调用parseQualifierElements解析qualifier元素最终会调用parseQualifierElement方法进行解析。这个东西我在xml中没有使用的过,但是在注解中还是会用到,简单看下,qualifier为AutowireCandidateQualifier的实例,有个attribute要处理,作为qualifier的BeanMetadataAttribute。 最后设置bean的resource(spirng的定义文件)和source(元素) 把bean的id从parseState中取出 返回生成的BeanDefinition 如果在BeanDefinition定义中没有id(beanName),则会创建并注册id到beanfactory中的beanDefinitionMap,请参考PropertyPlaceholderBeanDefinitionParser的部分解说 最后根据beanDefinition, beanName,aliases创建BeanDefinitionHolder,并返回。 如果BeanDefinitionHolder不为空,则会调用org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.decorateBeanDefinitionIfRequired(Element, BeanDefinitionHolder, BeanDefinition)进行装饰。 decorateBeanDefinitionIfRequired又会别装饰attribute和childNode,调用的都是decorateIfRequired方法处理。对于这些默认命名的其实是不会进行装饰的。 装饰完成调用org.springframework.beans.factory.support.BeanDefinitionReaderUtils.registerBeanDefinition(BeanDefinitionHolder, BeanDefinitionRegistry) 最终调用org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition(String, BeanDefinition)注册BeanDefinition 最终调用org.springframework.core.SimpleAliasRegistry.registerAlias(String, String)注册alias 根据BeanDefinitionHolder创建BeanComponentDefinition(这个对象注重bean之间的关联关系),调用ReaderContext,触发注册时间的监听器,监听器默认设么也不做因为是EmptyReaderEventListener。
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) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // Register the final decorated instance. 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)); } }
/** * Parses the supplied {@code <bean>} element. May return {@code null} * if there were errors during parse. Errors are reported to the * {@link org.springframework.beans.factory.parsing.ProblemReporter}. */ @Nullable public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) { String id = ele.getAttribute(ID_ATTRIBUTE); String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); List<String> aliases = new ArrayList<>(); if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } String beanName = id; if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { beanName = aliases.remove(0); if (logger.isTraceEnabled()) { logger.trace("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases"); } } if (containingBean == null) { checkNameUniqueness(beanName, aliases, ele); } AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) { if (!StringUtils.hasText(beanName)) { try { if (containingBean != null) { beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); } else { beanName = this.readerContext.generateBeanName(beanDefinition); // Register an alias for the plain bean class name, if still possible, // if the generator returned the class name plus a suffix. // This is expected for Spring 1.2/2.0 backwards compatibility. String beanClassName = beanDefinition.getBeanClassName(); if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { aliases.add(beanClassName); } } if (logger.isTraceEnabled()) { logger.trace("Neither XML 'id' nor 'name' specified - " + "using generated bean name [" + beanName + "]"); } } catch (Exception ex) { error(ex.getMessage(), ele); return null; } } String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; }
/** * Parse the bean definition itself, without regard to name or aliases. May return * {@code null} if problems occurred during the parsing of the bean definition. */ @Nullable public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, @Nullable BeanDefinition containingBean) { this.parseState.push(new BeanEntry(beanName)); String className = null; if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } String parent = null; if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } try { AbstractBeanDefinition bd = createBeanDefinition(className, parent); parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); parseMetaElements(ele, bd); parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); parseConstructorArgElements(ele, bd); parsePropertyElements(ele, bd); parseQualifierElements(ele, bd); bd.setResource(this.readerContext.getResource()); bd.setSource(extractSource(ele)); return bd; } catch (ClassNotFoundException ex) { error("Bean class [" + className + "] not found", ele, ex); } catch (NoClassDefFoundError err) { error("Class that bean class [" + className + "] depends on not found", ele, err); } catch (Throwable ex) { error("Unexpected failure during bean definition parsing", ele, ex); } finally { this.parseState.pop(); } return null; }
4.1.2.1 装载自定义的beanDefinitions
parseCustomElement方法会根据dom中的元素命名空间找到响应的一级解析器以后,在根据元素的二级命名空间找到二级解析器再由相应的二级解析器的doParse方法进行处理。
一级二级都放在hashMap中。这里面的东西有很多。我这里主要关注aop,tx两个。这可以看到一级和二级用的是组合模式,有利于提高代码的重用。一级是策略模式,由用户编写的spring配置文件指定。
命名空间的解析器由org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.getHandlerMappings()方法加载进来,查找所有jar包中的spring.handlers,然后加载响应的类。
如果需要自定义的命名空间就需要实现org.springframework.beans.factory.xml.NamespaceHandler,并使用init方法为他注入相关的二级解析器。 二级解析器需要实现org.springframework.beans.factory.xml.BeanDefinitionParser,真正解析某个元素。 需要定义自己的xsd文件,指定元素。 需要spring.schemas指定xsd文件的位置 需要spring.handlers指定一级解析类的类名
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele); if (namespaceUri == null) { return null; } NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); }
public NamespaceHandler resolve(String namespaceUri) { Map<String, Object> handlerMappings = getHandlerMappings(); Object handlerOrClassName = handlerMappings.get(namespaceUri); if (handlerOrClassName == null) { return null; } else if (handlerOrClassName instanceof NamespaceHandler) { return (NamespaceHandler) handlerOrClassName; } else { String className = (String) handlerOrClassName; try { Class<?> handlerClass = ClassUtils.forName(className, this.classLoader); if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) { throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface"); } NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass); namespaceHandler.init(); handlerMappings.put(namespaceUri, namespaceHandler); return namespaceHandler; } catch (ClassNotFoundException ex) { throw new FatalBeanException("Could not find NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]", ex); } catch (LinkageError err) { throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]", err); } } }
4.1.2.1.1 PropertyPlaceholderBeanDefinitionParser
调用org.springframework.beans.factory.xml.AbstractBeanDefinitionParser.parse方法。 该方法又会先调用org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser.parseInternal(Element, ParserContext)方法先内部创建BeanDefinition。 该方法以构造者模式使用BeanDefinitionBuilder来初步构造BeanDefinition。主要步骤: 1. 获取构造者 2. 如果该元素有父bean,会初步设置父bean的name,以后再分析处理。 3. 如果该元素有class类型(如果没有获取到,会尝试获取className,个别解析器有实现),会初步设置父bean的clss类型,以后再分析处理。 4. 设置bean的source 5. 如果该元素有父bean,则会设置scope为父bean 6. 如果该元素有懒加载,则会设置懒加载 7. 然后调用org.springframework.context.config.PropertyPlaceholderBeanDefinitionParser.doParse(Element, ParserContext, BeanDefinitionBuilder)方法,进一步解析 1. 该方法会先调用org.springframework.context.config.AbstractPropertyLoadingBeanDefinitionParser.doParse(Element, ParserContext, BeanDefinitionBuilder)方法,先解析通用的 1. 设置property文件的路径 2. 设置properties-ref 3. 设置file-encoding 4. 设置order 5. 设置ignore-resource-not-found 6. 设置local-override 7. 设置role为org.springframework.beans.factory.config.BeanDefinition.ROLE_INFRASTRUCTURE 2. 设置ignore-unresolvable 3. 设置system-properties-mode 4. 设置value-separator 5. 设置trim-values 6. 设置null-value 8. 最后用构造初步构造BeanDefinition,这里BeanDefinition的类是:org.springframework.beans.factory.support.GenericBeanDefinition 然后调用resolveId方法获取id 该方法先判定是否需要产生id,如果需要就最终会调用org.springframework.beans.factory.support.BeanDefinitionReaderUtils.generateBeanName(BeanDefinition, BeanDefinitionRegistry, boolean)方法产生并注入到spring容器里面 先获取BeanDefinition中的类名,如果类名为空,就根据父bean或者工厂创建generatedBeanName,然后在调用org.springframework.beans.factory.support.BeanDefinitionReaderUtils.uniqueBeanName(String, BeanDefinitionRegistry)产生唯一的id。该id由generatedBeanName和一个不重复的id构成,放在beanFactory的beanDefinitionMap的key中。 在获取aliases 而后根据id, BeanDefinition, aliases创建beanBeanDefinitionHolder 在调用registerBeanDefinition方法把BeanDefinition注入到beanFactory中,会调用一下两个方法: org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition(String, BeanDefinition)方法注入BeanDefinition。 会先验证, 然后根据id获取从beanDefinitionMap中获取bean, 如果BeanDefinition已经有了,根据情况,如果允许BeanDefinition覆盖,则覆盖,否则抛出异常。 如果没有BeanDefinition没有则会把id作为key,BeanDefinition作为value放入到beanFactory中的beanDefinitionMap中。beanDefinitionNames中增加id,从manualSingletonNames中移除id。这里支持创建bean实例的过程,增加BeanDefinition。 若果singletonObjects中包含id,会调用resetBeanDefinition,设置mergedBeanDefinitions中的bean的状态为true和从mergedBeanDefinitionHolders移除bean 如果isConfigurationFrozen为真,会调用clearByTypeCache清空allBeanNamesByType和singletonBeanNamesByType org.springframework.core.SimpleAliasRegistry.registerAlias(String, String)方法注入alias。 会先验证,alia不允许等于id 从aliasMap中获取已经注入的alia如果等于id话直接成功,否则判断是否可以覆盖,不能覆盖的直接抛出异常。 验证是否存在环型alia链如果存在直接抛出异常。 把alia存入aliasMap中,alia为key,id为value 如果需要触发相关的event的话,就去触发。默认触发,且以下三种事件: postProcessComponentDefinition,处理BeanDefinition的后置处理,对于properties来说是个空的实现。 org.springframework.beans.factory.xml.ParserContext.registerComponent(ComponentDefinition) 根据beanBeanDefinitionHolder创建BeanComponentDefinition,beanBeanDefinitionHolder用来保存bean之前的相互依关系 先从containingComponents里面查找第一个BeanDefinition,如果存在则把BeanComponentDefinition,作为查找到的bean的一个子BeanComponentDefinition 否则调用reader的fireComponentRegistered把BeanComponentDefinition注入到reader中,默认什么也不会做。
@Override @Nullable public final BeanDefinition parse(Element element, ParserContext parserContext) { AbstractBeanDefinition definition = parseInternal(element, parserContext); if (definition != null && !parserContext.isNested()) { try { String id = resolveId(element, definition, parserContext); if (!StringUtils.hasText(id)) { parserContext.getReaderContext().error( "Id is required for element '" + parserContext.getDelegate().getLocalName(element) + "' when used as a top-level tag", element); } String[] aliases = null; if (shouldParseNameAsAliases()) { String name = element.getAttribute(NAME_ATTRIBUTE); if (StringUtils.hasLength(name)) { aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name)); } } BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases); registerBeanDefinition(holder, parserContext.getRegistry()); if (shouldFireEvents()) { BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder); postProcessComponentDefinition(componentDefinition); parserContext.registerComponent(componentDefinition); } } catch (BeanDefinitionStoreException ex) { String msg = ex.getMessage(); parserContext.getReaderContext().error((msg != null ? msg : ex.toString()), element); return null; } } return definition; }
protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); String parentName = getParentName(element); if (parentName != null) { builder.getRawBeanDefinition().setParentName(parentName); } Class<?> beanClass = getBeanClass(element); if (beanClass != null) { builder.getRawBeanDefinition().setBeanClass(beanClass); } else { String beanClassName = getBeanClassName(element); if (beanClassName != null) { builder.getRawBeanDefinition().setBeanClassName(beanClassName); } } builder.getRawBeanDefinition().setSource(parserContext.extractSource(element)); BeanDefinition containingBd = parserContext.getContainingBeanDefinition(); if (containingBd != null) { // Inner bean definition must receive same scope as containing bean. builder.setScope(containingBd.getScope()); } if (parserContext.isDefaultLazyInit()) { // Default-lazy-init applies to custom bean definitions as well. builder.setLazyInit(true); } doParse(element, parserContext, builder); return builder.getBeanDefinition(); }
@Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { super.doParse(element, parserContext, builder); builder.addPropertyValue("ignoreUnresolvablePlaceholders", Boolean.valueOf(element.getAttribute("ignore-unresolvable"))); String systemPropertiesModeName = element.getAttribute(SYSTEM_PROPERTIES_MODE_ATTRIBUTE); if (StringUtils.hasLength(systemPropertiesModeName) && !systemPropertiesModeName.equals(SYSTEM_PROPERTIES_MODE_DEFAULT)) { builder.addPropertyValue("systemPropertiesModeName", "SYSTEM_PROPERTIES_MODE_" + systemPropertiesModeName); } if (element.hasAttribute("value-separator")) { builder.addPropertyValue("valueSeparator", element.getAttribute("value-separator")); } if (element.hasAttribute("trim-values")) { builder.addPropertyValue("trimValues", element.getAttribute("trim-values")); } if (element.hasAttribute("null-value")) { builder.addPropertyValue("nullValue", element.getAttribute("null-value")); } }
4.1.2.1.2 ConfigBeanDefinitionParser
根据元素的标签和元素创建CompositeComponentDefinition(这是一个中组合的bean定义) 把CompositeComponentDefinition存入parserContext中的containingComponents中 调用configureAutoProxyCreator配置自动代理 先调用org.springframework.aop.config.AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(ParserContext, Element),创建代理类的BeanDefinition 先调用org.springframework.aop.config.AopConfigUtils.registerOrEscalateApcAsRequired(Class<?>, BeanDefinitionRegistry, Object)创建BeanDefinition 如果已经有自动代理的BeanDefinition,且已经有的BeanDefinition的优先级小于要创建的,则进行覆盖。 如果没有则创建BeanDefinition为RootBeanDefinition的实例(这种类型的beanDefinition在beanFactory中有一定的特殊作用),设置source,设置order,设置role 并注入到beanFactory中,id为rg.springframework.aop.config.internalAutoProxyCreator,class为org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator 调用useClassProxyingIfNecessary设置自动代理的proxyTargetClass和exposeProxy 调用 根据beanDefinition,id创建BeanComponentDefinition,并注入到parserContext的CompositeComponentDefinition中 遍历子元素,根据子元素的二级标签,调用响应的parser进行解析: parsePointcut解析pointCut 首先获取id,和 expression 根据id创建PointcutEntry并且放入到parseState中 调用createPointcutDefinition根据expression创建BeanDefinition(RootBeanDefinition的实例),并设置class为org.springframework.aop.aspectj.AspectJExpressionPointcut,scope,synthetic, 和expression作为property 设置source 然后根据id和beanDefinition注入到beanFactory的beanDefinitionMap中。 根据id,BeanDefinition,expression创建PointcutComponentDefinition,并注入到parserContext的CompositeComponentDefinition中 从parseState中移除PointcutEntry 并返回beanDefinition parseAdvisor解析advice 首先调用createAdvisorBeanDefinition创建BeanDefinition为RootBeanDefinition的实例。同时创建并注入adviceRef为property,同时创建并注入orderRef为property 获取id 根据id创建AdvisorEntry并且放入到parseState中 然后根据id注入到beanFactory的beanDefinitionMap中 调用parsePointcutProperty对pointCut做一些简单的验证 根据pointCut是beanDefinition还是String,分别做处理,但是都是把pointCut放入到advice的beanDefinition中,创建AdvisorComponentDefinition,并注入到parserContext的CompositeComponentDefinition中 从parseState中移除AdvisorEntry parseAspect 没有用过aspect标签,看起来好像比较复杂,是上面两个的集合 把CompositeComponentDefinition从parserContext中的containingComponents取出,并注入CompositeComponentDefinition到beanFactory中。
@Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element)); parserContext.pushContainingComponent(compositeDef); configureAutoProxyCreator(parserContext, element); List<Element> childElts = DomUtils.getChildElements(element); for (Element elt: childElts) { String localName = parserContext.getDelegate().getLocalName(elt); if (POINTCUT.equals(localName)) { parsePointcut(elt, parserContext); } else if (ADVISOR.equals(localName)) { parseAdvisor(elt, parserContext); } else if (ASPECT.equals(localName)) { parseAspect(elt, parserContext); } } parserContext.popAndRegisterContainingComponent(); return null; }
private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) { String id = pointcutElement.getAttribute(ID); String expression = pointcutElement.getAttribute(EXPRESSION); AbstractBeanDefinition pointcutDefinition = null; try { this.parseState.push(new PointcutEntry(id)); pointcutDefinition = createPointcutDefinition(expression); pointcutDefinition.setSource(parserContext.extractSource(pointcutElement)); String pointcutBeanName = id; if (StringUtils.hasText(pointcutBeanName)) { parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition); } else { pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition); } parserContext.registerComponent( new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression)); } finally { this.parseState.pop(); } return pointcutDefinition; }
private void parseAdvisor(Element advisorElement, ParserContext parserContext) { AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext); String id = advisorElement.getAttribute(ID); try { this.parseState.push(new AdvisorEntry(id)); String advisorBeanName = id; if (StringUtils.hasText(advisorBeanName)) { parserContext.getRegistry().registerBeanDefinition(advisorBeanName, advisorDef); } else { advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef); } Object pointcut = parsePointcutProperty(advisorElement, parserContext); if (pointcut instanceof BeanDefinition) { advisorDef.getPropertyValues().add(POINTCUT, pointcut); parserContext.registerComponent( new AdvisorComponentDefinition(advisorBeanName, advisorDef, (BeanDefinition) pointcut)); } else if (pointcut instanceof String) { advisorDef.getPropertyValues().add(POINTCUT, new RuntimeBeanReference((String) pointcut)); parserContext.registerComponent( new AdvisorComponentDefinition(advisorBeanName, advisorDef)); } } finally { this.parseState.pop(); } }
private void parseAspect(Element aspectElement, ParserContext parserContext) { String aspectId = aspectElement.getAttribute(ID); String aspectName = aspectElement.getAttribute(REF); try { this.parseState.push(new AspectEntry(aspectId, aspectName)); List<BeanDefinition> beanDefinitions = new ArrayList<>(); List<BeanReference> beanReferences = new ArrayList<>(); List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS); for (int i = METHOD_INDEX; i < declareParents.size(); i++) { Element declareParentsElement = declareParents.get(i); beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext)); } // We have to parse "advice" and all the advice kinds in one loop, to get the // ordering semantics right. NodeList nodeList = aspectElement.getChildNodes(); boolean adviceFoundAlready = false; for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); if (isAdviceNode(node, parserContext)) { if (!adviceFoundAlready) { adviceFoundAlready = true; if (!StringUtils.hasText(aspectName)) { parserContext.getReaderContext().error( "<aspect> tag needs aspect bean reference via 'ref' attribute when declaring advices.", aspectElement, this.parseState.snapshot()); return; } beanReferences.add(new RuntimeBeanReference(aspectName)); } AbstractBeanDefinition advisorDefinition = parseAdvice( aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences); beanDefinitions.add(advisorDefinition); } } AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition( aspectElement, aspectId, beanDefinitions, beanReferences, parserContext); parserContext.pushContainingComponent(aspectComponentDefinition); List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT); for (Element pointcutElement : pointcuts) { parsePointcut(pointcutElement, parserContext); } parserContext.popAndRegisterContainingComponent(); } finally { this.parseState.pop(); } }
4.1.2.1.2 TxAdviceBeanDefinitionParser
调用org.springframework.beans.factory.xml.AbstractBeanDefinitionParser.parse方法。 所以整体过程跟org.springframework.context.config.PropertyPlaceholderBeanDefinitionParser的差不多。 我们这里主要看下TxAdviceBeanDefinitionParser内部的doParse方法。 会先设置transactionManager为一个PropertyReference 调用解析parseAttributeSource解析attribute及其method标签。最后attribute会被做成一个BeanDefinition为RootBeanDefinition的实例,并把method做成TypedStringValue,所有的method做成一个map,作为attribute的一个property属性。
@Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { builder.addPropertyReference("transactionManager", TxNamespaceHandler.getTransactionManagerName(element)); List<Element> txAttributes = DomUtils.getChildElementsByTagName(element, ATTRIBUTES_ELEMENT); if (txAttributes.size() > 1) { parserContext.getReaderContext().error( "Element <attributes> is allowed at most once inside element <advice>", element); } else if (txAttributes.size() == 1) { // Using attributes source. Element attributeSourceElement = txAttributes.get(0); RootBeanDefinition attributeSourceDefinition = parseAttributeSource(attributeSourceElement, parserContext); builder.addPropertyValue("transactionAttributeSource", attributeSourceDefinition); } else { // Assume annotations source. builder.addPropertyValue("transactionAttributeSource", new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource")); } }
4.2 prepareBeanFactory
设置ClassLoader 创建并设置beanExpression为StandardBeanExpressionResolver 创建并增加propertyEditorRegistrar为ResourceEditorRegistrar放入beanFactory中的propertyEditorRegistrars 创建并设置BeanPostProcessor为ApplicationContextAwareProcessor 增加ignoreDependencyInterface的类:放入beanFactory中的ignoredDependencyInterfaces EnvironmentAware EmbeddedValueResolverAware ResourceLoaderAware ApplicationEventPublisherAware MessageSourceAware ApplicationContextAware 增加registerResolvableDependency放入beanfactory中的resolvableDependencies BeanFactory类型为this ResourceLoader为this ApplicationEventPublisher为this ApplicationContext为this 创建并增加ropertyEditorRegistrar为ApplicationListenerDetector 如果设置了loadTimeWeaver,则会增加BeanPostProcessor,并设置TempClassLoader 如果设置了environment了,则会注册环境bean到beanFactory 如果设置了systemProperties,则会注册系统属性bean到beanFactory 如果设置了systemEnvironment,则会注册系统环境bean到beanFactory
/** * Configure the factory's standard context characteristics, * such as the context's ClassLoader and post-processors. * @param beanFactory the BeanFactory to configure */ protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // Tell the internal bean factory to use the context's class loader etc. beanFactory.setBeanClassLoader(getClassLoader()); beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // Configure the bean factory with context callbacks. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); // BeanFactory interface not registered as resolvable type in a plain factory. // MessageSource registered (and found for autowiring) as a bean. beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // Register early post-processor for detecting inner beans as ApplicationListeners. beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); // Detect a LoadTimeWeaver and prepare for weaving, if found. if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); // Set a temporary ClassLoader for type matching. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } // Register default environment beans. if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } }
4.3 postProcessBeanFactory
创建并增加BeanPostProcessor为ServletContextAwareProcessor 增加ignoreDependencyInterface的类: ServletContextAware ServletConfigAware 调用org.springframework.web.context.support.WebApplicationContextUtils.registerWebApplicationScopes(ConfigurableListableBeanFactory, ServletContext)注册servletContext 创建并把 request注入到BeanFactory中的scopes中,key为requset,value为RequestScope 创建并把 session注入到BeanFactory中的scopes中,key为session,value为SessionScope 创建并把 ServletContextScope注入到BeanFactory中的scopes中,key为application,value为ServletContextScope 并设置ServletContext的属性为ServletContextScope 增加registerResolvableDependency放入beanfactory中的resolvableDependencies ServletRequest类型为RequestObjectFactory ServletResponse类型为ResponseObjectFactory HttpSession类型为SessionObjectFactory WebRequest类型为WebRequestObjectFactory 调用org.springframework.web.context.support.WebApplicationContextUtils.registerEnvironmentBeans(ConfigurableListableBeanFactory, ServletContext, ServletConfig)注册环境 如果beanFactory中没有id为servletContext的bean,创建并注册servletContext到beanFactory 如果beanFactory中没有id为servletConfig的bean,创建并注册servletConfig到beanFactory 如果beanFactory中没有id为contextParameters的bean,解析servletContext,获取contextParameters(不可以修改的)创建并注册contextParameters到beanFactory 如果beanFactory中没有id为contextAttributes的bean,解析servletContext,获取contextAttributes(不可修改的)创建并注册contextAttributes到beanFactory
/** * Register request/session scopes, a {@link ServletContextAwareProcessor}, etc. */ @Override protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig)); beanFactory.ignoreDependencyInterface(ServletContextAware.class); beanFactory.ignoreDependencyInterface(ServletConfigAware.class); WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext); WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig); }
4.4 invokeBeanFactoryPostProcessors 创建processor
初始化,并调用所有已经注册的BeanFactoryPostProcessor,来修改已经解析到的BeanDefinition,或者加入新的beanDefinition
调用invokeBeanFactoryPostProcessors实例化beanFactory中的beanFactoryPostProcessors 先实例化实现了PriorityOrdered的BeanFactoryPostProcessor 后实例化实现了Ordered的BeanFactoryPostProcessor 最后实例化常规的BeanFactoryPostProcessor 实例化是调用invokeBeanDefinitionRegistryPostProcessors进行实例化,这个过程有可能注入其他的BeanFactoryPostProcessor。 最后调用invokeBeanFactoryPostProcessors先处理registryProcessors然后在处理regularPostProcessors。 从beanFactory中获取BeanFactoryPostProcessor,并分成3类,PriorityOrdered和Ordered还有noOrdered,分别调用invokeBeanFactoryPostProcessors 最后清理MetadataCache。 如果beanFactory包含loadTimeWeaver,创建并增加LoadTimeWeaverAwareProcessor,创建并设置ContextTypeMatchClassLoader
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor) if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any. Set<String> processedBeans = new HashSet<>(); if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); } } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! // Separate between BeanDefinitionRegistryPostProcessors that implement // PriorityOrdered, Ordered, and the rest. List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate = true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); } // Now, invoke the postProcessBeanFactory callback of all processors handled so far. invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // Invoke factory processors registered with the context instance. invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered. List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size()); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors. List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size()); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); // Clear cached merged bean definitions since the post-processors might have // modified the original metadata, e.g. replacing placeholders in values... beanFactory.clearMetadataCache(); }
/** * Invoke the given BeanDefinitionRegistryPostProcessor beans. */ private static void invokeBeanDefinitionRegistryPostProcessors( Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) { for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) { postProcessor.postProcessBeanDefinitionRegistry(registry); } }
4.4.1 MapperScannerConfigurer
主要是用来扫描并加载basePackage下的class文件,成为beanDefinition。
如果为真,会先调用processPropertyPlaceHolders处理property,从代码来看,这似乎是支持property形式的配置,不过这里使用的xml形式的配置 创建ClassPathMapperScanner,并进行如下设置: addToConfig annotationClass markerInterface sqlSessionFactory sqlSessionTemplate sqlSessionFactoryBeanName sqlSessionTemplateBeanName applicationContext nameGenerator mapperFactoryBeanClass lazyInitialization defaultScope filter 后调用scan方法扫描。scan方法又会调用doScan进行扫描。 先调用super的doScan,获取basepackage类的beanDefinition 调用scanCandidateComponents方法,扫描basePackage下的每一个class文件,并生成对应的beanDefinition 使用ResourcePatternResolver实际上为WebApplicationContext扫描basePackge下的resource(实际上为class文件) 为扫描到的每一个class创建BeanDefinition为ScannedGenericBeanDefinition的实例 设置class的BeanDefinition的scope,metaScope,id 如果是AbstractBeanDefinition的实例,调用postProcessBeanDefinition,进行一些默认的创造比如 lazyInit AutowireMode DependencyChec InitMethodName EnforceInitMethod DestroyMethodName EnforceDestroyMethod autowireCandidatePatterns 如果是AnnotatedBeanDefinition的实例,设置metaData 如果校验通过(没有已经存在的id) 则会根据id,beanDefinition,创建BeanDefinitionHolder 然后通过org.springframework.context.annotation.AnnotationConfigUtils.applyScopedProxyMode把BeanDefinitionHolder设置为它的代理或者他自己 最后把beanDefinition注入到beanFactory中 后调用processBeanDefinitions,进一步处理上面获取到的beanDefinition className addToConfig factoryBeanObjectType sqlSessionFactory sqlSessionTemplate LazyInit Scope 如果不是singleton创建代理,并注入到beanFactory 如果是注解的配置,调用AnnotationConfigUtils.registerAnnotationConfigProcessors想beanFactory中注入注解的解析器 如果beanFactory的DependencyComparator不是AnnotationAwareOrderComparator,则设置是 如果beanFactory的AutowireCandidateResolver不是ContextAnnotationAutowireCandidateResolver,则设置是 创建并注入beanDefinition,org.springframework.context.annotation.internalConfigurationAnnotationProcessor(实际的类类型为org.springframework.context.annotation.ConfigurationClassPostProcessor) 创建并注入beanDefinition,org.springframework.context.annotation.internalAutowiredAnnotationProcessor 创建并注入beanDefinition,org.springframework.context.annotation.internalCommonAnnotationProcessor 创建并注入beanDefinition,org.springframework.context.annotation.internalPersistenceAnnotationProcessor 创建并注入beanDefinition,org.springframework.context.event.internalEventListenerFactory
@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { if (this.processPropertyPlaceHolders) { processPropertyPlaceHolders(); } ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); scanner.setAddToConfig(this.addToConfig); scanner.setAnnotationClass(this.annotationClass); scanner.setMarkerInterface(this.markerInterface); scanner.setSqlSessionFactory(this.sqlSessionFactory); scanner.setSqlSessionTemplate(this.sqlSessionTemplate); scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName); scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName); scanner.setResourceLoader(this.applicationContext); scanner.setBeanNameGenerator(this.nameGenerator); scanner.setMapperFactoryBeanClass(this.mapperFactoryBeanClass); if (StringUtils.hasText(lazyInitialization)) { scanner.setLazyInitialization(Boolean.valueOf(lazyInitialization)); } if (StringUtils.hasText(defaultScope)) { scanner.setDefaultScope(defaultScope); } scanner.registerFilters(); scanner.scan( StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS)); }
/** * Perform a scan within the specified base packages. * @param basePackages the packages to check for annotated classes * @return number of beans registered */ public int scan(String... basePackages) { int beanCountAtScanStart = this.registry.getBeanDefinitionCount(); doScan(basePackages); // Register annotation config processors, if necessary. if (this.includeAnnotationConfig) { AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); } return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart); }
@Override public Set<BeanDefinitionHolder> doScan(String... basePackages) { Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages); if (beanDefinitions.isEmpty()) { LOGGER.warn(() -> "No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration."); } else { processBeanDefinitions(beanDefinitions); } return beanDefinitions; }
protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>(); for (String basePackage : basePackages) { Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { 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); registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) { AbstractBeanDefinition definition; BeanDefinitionRegistry registry = getRegistry(); for (BeanDefinitionHolder holder : beanDefinitions) { definition = (AbstractBeanDefinition) holder.getBeanDefinition(); boolean scopedProxy = false; if (ScopedProxyFactoryBean.class.getName().equals(definition.getBeanClassName())) { definition = (AbstractBeanDefinition) Optional .ofNullable(((RootBeanDefinition) definition).getDecoratedDefinition()) .map(BeanDefinitionHolder::getBeanDefinition).orElseThrow(() -> new IllegalStateException( "The target bean definition of scoped proxy bean not found. Root bean definition[" + holder + "]")); scopedProxy = true; } String beanClassName = definition.getBeanClassName(); LOGGER.debug(() -> "Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + beanClassName + "' mapperInterface"); // the mapper interface is the original class of the bean // but, the actual class of the bean is MapperFactoryBean definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); // issue #59 definition.setBeanClass(this.mapperFactoryBeanClass); definition.getPropertyValues().add("addToConfig", this.addToConfig); // Attribute for MockitoPostProcessor // https://github.com/mybatis/spring-boot-starter/issues/475 definition.setAttribute(FACTORY_BEAN_OBJECT_TYPE, beanClassName); boolean explicitFactoryUsed = false; if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) { definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName)); explicitFactoryUsed = true; } else if (this.sqlSessionFactory != null) { definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory); explicitFactoryUsed = true; } if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) { if (explicitFactoryUsed) { LOGGER.warn( () -> "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."); } definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName)); explicitFactoryUsed = true; } else if (this.sqlSessionTemplate != null) { if (explicitFactoryUsed) { LOGGER.warn( () -> "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."); } definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate); explicitFactoryUsed = true; } if (!explicitFactoryUsed) { LOGGER.debug(() -> "Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'."); definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); } definition.setLazyInit(lazyInitialization); if (scopedProxy) { continue; } if (ConfigurableBeanFactory.SCOPE_SINGLETON.equals(definition.getScope()) && defaultScope != null) { definition.setScope(defaultScope); } if (!definition.isSingleton()) { BeanDefinitionHolder proxyHolder = ScopedProxyUtils.createScopedProxy(holder, registry, true); if (registry.containsBeanDefinition(proxyHolder.getBeanName())) { registry.removeBeanDefinition(proxyHolder.getBeanName()); } registry.registerBeanDefinition(proxyHolder.getBeanName(), proxyHolder.getBeanDefinition()); } } }
4.4.1 ConfigurationClassPostProcessor
这个一部分我就没有看太细致了,根据上mybatis中的MapperScannerConfigurer,就能看出来,针对不同情况,使用不同解析器,生成bean的定义,只不过ConfigurationClassPostProcessor主要针对的是注解。
先会从beanFactory获取已经注入的beanDefinition的id的列表 从上一步的列表中进行过滤,过滤掉以下两种,并根据configuration的proxyBeanMethods属性设置beanDefinition的configurationClass属性,并把BeanDefinition包裹成BeanDefinitionHolder 已经有configurationClass属性的(说明已经处理过了) class上没有Configuration的注解的BeanDefinition(通过ConfigurationClassUtils.checkConfigurationClassCandidate) 对过滤掉的列表进行排序 如果beanFactory是SingletonBeanRegistry的实例,调用beanFactory的getSingleton获取org.springframework.context.annotation.internalConfigurationBeanNameGenerator,如果刚刚获取到的不为null,则覆盖componentScanBeanNameGenerator和importBeanNameGenerator 如果当前的env是空的,则会创建StandardEnvironment为env 创建ConfigurationClassParser,创建时会创建ComponentScanAnnotationParser,进一步解析每一个过滤好的BeanDefinition, 对于AnnotatedBeanDefinition类型的beanDefinition 创建ConfigurationClass。 从configurationClasses中获取缓存的configClass 如果缓存中有,且configClass是import的,缓存中的也是,则合并。 如果缓存中有,且configClass不是import的, 结束 如果缓存没有,移除缓存中configClass和knownSuperclasses缓存移除。 创建并加载SourceClass,然后调用doProcessConfigurationClass递归的处理它及其父类。 如果有@Component注解调用processMemberClasses进行处理。 调用getMemberClasses获取父类和父接口 如果source是class,则调用JDK API获取declaredClass 其他,则调用ASM API获取declaredClass 取出同时满足以下两条 调用ConfigurationClassUtils.isConfigurationCandidate时返回ture(不是接口,至少包含@Component,@ComponentScan,@Import,@ImportResource之一 或者 方法包含有@Bean) memberClass的metaData中不包含configClass(最开始的configClass) 对过滤的memberClasses进行排序 对于每一个过滤后的memberClass调用processConfigurationClass进行递归处理。同时借助importStack,来判断有没有循环继承。 调用processPropertySource处理@PropertySource 获取name,获取encoding,获取value。 如果PropertySource带有自己的声明的工厂。 调用this.environment.resolveRequiredPlaceholders(location)获取resolvedLocation。这里的调用相当长。不在细看了 调用this.resourceLoader.getResource(resolvedLocation);获取resource 调用工厂创建ResourcePropertySource,并缓存到propertySources里,如果已经有了,根据情况会覆盖或者合并 加入configurationClasses缓存中。 对于AbstractBeanDefinition且含有class的beanDefinition 其他
/** * 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) { List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); String[] candidateNames = registry.getBeanDefinitionNames(); for (String beanName : candidateNames) { BeanDefinition beanDef = registry.getBeanDefinition(beanName); if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) { if (logger.isDebugEnabled()) { logger.debug("Bean definition has already been processed as a configuration class: " + beanDef); } } else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); } } // Return immediately if no @Configuration classes were found if (configCandidates.isEmpty()) { return; } // Sort by previously determined @Order value, if applicable configCandidates.sort((bd1, bd2) -> { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); return Integer.compare(i1, i2); }); // Detect any custom bean name generation strategy supplied through the enclosing application context SingletonBeanRegistry sbr = null; if (registry instanceof SingletonBeanRegistry) { sbr = (SingletonBeanRegistry) registry; if (!this.localBeanNameGeneratorSet) { BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton( AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR); if (generator != null) { this.componentScanBeanNameGenerator = generator; this.importBeanNameGenerator = generator; } } } if (this.environment == null) { this.environment = new StandardEnvironment(); } // 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(); Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); configClasses.removeAll(alreadyParsed); // Read the model and create bean definitions based on its content if (this.reader == null) { this.reader = new ConfigurationClassBeanDefinitionReader( registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry()); } this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses); candidates.clear(); if (registry.getBeanDefinitionCount() > candidateNames.length) { String[] newCandidateNames = registry.getBeanDefinitionNames(); Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames)); Set<String> alreadyParsedClasses = new HashSet<>(); for (ConfigurationClass configurationClass : alreadyParsed) { alreadyParsedClasses.add(configurationClass.getMetadata().getClassName()); } for (String candidateName : newCandidateNames) { if (!oldCandidateNames.contains(candidateName)) { BeanDefinition bd = registry.getBeanDefinition(candidateName); if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && !alreadyParsedClasses.contains(bd.getBeanClassName())) { candidates.add(new BeanDefinitionHolder(bd, candidateName)); } } } candidateNames = newCandidateNames; } } while (!candidates.isEmpty()); // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) { sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry()); } if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) { // Clear cache in externally provided MetadataReaderFactory; this is a no-op // for a shared cache since it'll be cleared by the ApplicationContext. ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache(); } }
public void parse(Set<BeanDefinitionHolder> configCandidates) { for (BeanDefinitionHolder holder : configCandidates) { BeanDefinition bd = holder.getBeanDefinition(); try { if (bd instanceof AnnotatedBeanDefinition) { parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName()); } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) { parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName()); } else { parse(bd.getBeanClassName(), holder.getBeanName()); } } catch (BeanDefinitionStoreException ex) { throw ex; } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex); } } this.deferredImportSelectorHandler.process(); }
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException { processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER); }
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException { if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) { return; } ConfigurationClass existingClass = this.configurationClasses.get(configClass); if (existingClass != null) { if (configClass.isImported()) { if (existingClass.isImported()) { existingClass.mergeImportedBy(configClass); } // Otherwise ignore new imported config class; existing non-imported class overrides it. return; } else { // Explicit bean definition found, probably replacing an import. // Let's remove the old one and go with the new one. this.configurationClasses.remove(configClass); this.knownSuperclasses.values().removeIf(configClass::equals); } } // Recursively process the configuration class and its superclass hierarchy. SourceClass sourceClass = asSourceClass(configClass, filter); do { sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter); } while (sourceClass != null); this.configurationClasses.put(configClass, configClass); }
4.5 registerBeanPostProcessors
初始化,并注册BeanPostProcessor到beanFactory中的registerSingleton,跟上一步类似,增加了更多默认的BeanPostProcessor
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this); }
public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); // Register BeanPostProcessorChecker that logs an info message when // a bean is created during BeanPostProcessor instantiation, i.e. when // a bean is not eligible for getting processed by all BeanPostProcessors. int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)); // Separate between BeanPostProcessors that implement PriorityOrdered, // Ordered, and the rest. List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<BeanPostProcessor> internalPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); priorityOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First, register the BeanPostProcessors that implement PriorityOrdered. sortPostProcessors(priorityOrderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); // Next, register the BeanPostProcessors that implement Ordered. List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size()); for (String ppName : orderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); orderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } sortPostProcessors(orderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, orderedPostProcessors); // Now, register all regular BeanPostProcessors. List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size()); for (String ppName : nonOrderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); nonOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); // Finally, re-register all internal BeanPostProcessors. sortPostProcessors(internalPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, internalPostProcessors); // Re-register post-processor for detecting inner beans as ApplicationListeners, // moving it to the end of the processor chain (for picking up proxies etc). beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); }
4.6 initMessageSource
创建,初始化,并注册MessageSource到beanFactory中的registerSingleton
protected void initMessageSource() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) { this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class); // Make MessageSource aware of parent MessageSource. if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) { HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource; if (hms.getParentMessageSource() == null) { // Only set parent context as parent MessageSource if no parent MessageSource // registered already. hms.setParentMessageSource(getInternalParentMessageSource()); } } if (logger.isTraceEnabled()) { logger.trace("Using MessageSource [" + this.messageSource + "]"); } } else { // Use empty MessageSource to be able to accept getMessage calls. DelegatingMessageSource dms = new DelegatingMessageSource(); dms.setParentMessageSource(getInternalParentMessageSource()); this.messageSource = dms; beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource); if (logger.isTraceEnabled()) { logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]"); } } }
4.7 initApplicationEventMulticaster
创建,初始化,并注册ApplicationEventMulticaster到beanFactory中的registerSingleton
protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isTraceEnabled()) { logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); if (logger.isTraceEnabled()) { logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " + "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]"); } } }
4.8 onRefresh
创建,初始化,并注册themeSource到beanFactory中的registerSingleton
@Override protected void onRefresh() { this.themeSource = UiApplicationContextUtils.initThemeSource(this); }
public static ThemeSource initThemeSource(ApplicationContext context) { if (context.containsLocalBean(THEME_SOURCE_BEAN_NAME)) { ThemeSource themeSource = context.getBean(THEME_SOURCE_BEAN_NAME, ThemeSource.class); // Make ThemeSource aware of parent ThemeSource. if (context.getParent() instanceof ThemeSource && themeSource instanceof HierarchicalThemeSource) { HierarchicalThemeSource hts = (HierarchicalThemeSource) themeSource; if (hts.getParentThemeSource() == null) { // Only set parent context as parent ThemeSource if no parent ThemeSource // registered already. hts.setParentThemeSource((ThemeSource) context.getParent()); } } if (logger.isDebugEnabled()) { logger.debug("Using ThemeSource [" + themeSource + "]"); } return themeSource; } else { // Use default ThemeSource to be able to accept getTheme calls, either // delegating to parent context's default or to local ResourceBundleThemeSource. HierarchicalThemeSource themeSource = null; if (context.getParent() instanceof ThemeSource) { themeSource = new DelegatingThemeSource(); themeSource.setParentThemeSource((ThemeSource) context.getParent()); } else { themeSource = new ResourceBundleThemeSource(); } if (logger.isDebugEnabled()) { logger.debug("Unable to locate ThemeSource with name '" + THEME_SOURCE_BEAN_NAME + "': using default [" + themeSource + "]"); } return themeSource; } }
4.9 registerListeners
为EventMulticaster增加ApplicationListener,并发布multicaster的设置事件
protected void registerListeners() { // Register statically specified listeners first. for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let post-processors apply to them! String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } // Publish early application events now that we finally have a multicaster... Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (!CollectionUtils.isEmpty(earlyEventsToProcess)) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); } } }
4.10 finishBeanFactoryInitialization 创建bean
把BeanDefinition变成真正的bean对象到beanFactory中的registerSingleton和SingletonObjects(对于大多数bean来说)
如果beanFactory包含名称为ConversionService的bean,且是ConversionService的子类,则设置conversionService 如果beanFactory中没有value resolver,则会创建,并注册一个默认的value resolver 如果beanFactory中有LoadTimeWeaverAware类型的bean,调用getBean获取所有该类型的Bean 设置beanFactory的tempClassLoader为null 调用beanFactory的freezeConfiguration,锁住配置,主要为beanDefinitionMap等等。 调用beanFactory的preInstantiateSingletons创建所有的非懒加载的bean的实例
/** * Finish the initialization of this context's bean factory, * initializing all remaining singleton beans. */ 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(); }
4.10.1 preInstantiateSingletons
复制beanDefinitionNames,并对其进行遍历。 调用getMergedLocalBeanDefinition,从mergedBeanDefinitions中或去mere相关的信息。 从mergedBeanDefinitions中,直接获取RootBeanDefinition 上一步获取不为null,且state表明不需要再次合并,直接返回获取的RootBeanDefinition 调用getMergedBeanDefinition,从新合并beanDefinition.(这里主要处理父子bean的关系) 不处理abstract,懒加载的,还有不是Singleton的BeanDefinition 调用isFactoryBean判断是不是FactoryBean 调用transformedBeanName,转换名称 调用getSingleton,获取从当前beanFactory获取单例。 会先从singletonObjects中获取单例。 如果单例为空,且,singletonsCurrentlyInCreation中包含该单例的id,从earlySingletonObjects获取单例。 如果单例为空,且,allowEarlyReference为真。锁住singletonObjects, 从singletonObjects中获取单例。 如果单例为空,且,singletonsCurrentlyInCreation中包含该单例的id,从earlySingletonObjects获取单例。 如果单例为空,且,singletonFactories中包含该单例的singletonFactory,如果singletonFactory不为空从singletonFactory获取单例并移除,并放入earlySingletonObjects 如果单例不为null,返回单例是不是FactoryBean的实例。 如果单例为null,且本容器没有beanDefinition,获取父容器,父容器不为null,且父容器为ConfigurableBeanFactory的实例,父容器调用isFactoryBean方法,并直接返回。 如果单例为null,且本容器有beanDefinition,从调用isFactoryBean,从合并的beanDefinition进行判断。 如果beanDefinition中有isFactoryBean,不等于null,直接返回该值 否者进行一系列的处理,返回beanDefinition的Type推断class(这一部分就不在细致的看了)是否是FactoryBean的子类。 是FactoryBean 判断factoryBean是否需要迫切加载,如果是则调用调用beanFactory的getBean方法 不是FactoryBean 调用beanFactory的getBean方法,该方法主要功能是:如果已经有bean,直接获取,如果没有则创建,初始化。最终调用doGetBean。
@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) { 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); } } } // Trigger post-initialization callback for all applicable beans... for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { smartSingleton.afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } }
4.10.2 getBean
该方法主要功能是:如果已经有bean,直接获取,如果没有则创建,初始化。最终调用doGetBean。
调用transformedBeanName,转换名称 调用getSingleton,获取从当前beanFactory获取单例。 如果单例不为null,调用getObjectForBeanInstance方法,进行进一步处理。 如果单例为null 调用isPrototypeCurrentlyInCreation判断单例是否正在创建,如果是则抛出异常 获取父BeanFactory,如果父beanFactory包含BeanDefinition,则调用父beanFactory的getBean方法,并直接返回。 如果不是仅仅检查类型,则标记该bean正在被创建,alreadyCreated放入bean的id 调用getMergedLocalBeanDefinition获取当前容器中所有相关的beanDefinition和合集。 判断bean的类型是不是抽象的如果是,则抛出异常。 检查该bean是否有依赖,从合并的beanDefinition中。 如果有,对于每一个依赖,调用registerDependentBean注册依赖到dependentBeanMap和dependenciesForBeanMap,并递归调用beanFactory的getBean方法,获取(有可能伴随着创建)依赖bean。 如果该bean是单例的 调用getSingleton方法, 如果该bean是多利的 则先调用beforePrototypeCreation,处理prototypesCurrentlyInCreation,和beanNameSet,标识正在创建 后直接调用createBean方法 最后调用afterPrototypeCreation,清理prototypesCurrentlyInCreation,和beanNameSet,标识创建完成 最后调用getObjectForBeanInstance,创建class为factoryBean的bean。 其他情况 获取scope,并对scope做个验证 调用scope的get方法,并使用lambda表达式,创建一个beanFactory。 创建bean实例的时候,调用先调用beforePrototypeCreation,后调用createBean方法,最后在调用afterPrototypeCreation,如果发生异常,则会销毁创建的失败的bean。 最后调用getObjectForBeanInstance,创建class为factoryBean的bean。 检查创建的bean和想要的type是否匹配 如果不匹配则抛出异常。匹配则返回bean。
@Override public <T> T getBean(Class<T> requiredType) throws BeansException { return getBean(requiredType, (Object[]) null); }
@SuppressWarnings("unchecked") protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 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(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType != null) { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { 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 dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); try { getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // Create bean instance. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { 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); } else { String scopeName = mbd.getScope(); if (!StringUtils.hasLength(scopeName)) { throw new IllegalStateException("No scope name defined for bean 麓" + beanName + "'"); } 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, () -> { 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; } } // Check if required type matches the type of the actual bean instance. if (requiredType != null && !requiredType.isInstance(bean)) { try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } catch (TypeMismatchException ex) { if (logger.isTraceEnabled()) { logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }
4.10.3 getSingleton
锁住singletonObjects 从singletonObjects中获取bean 如果bean不等于null直接返回bean 如果bean等于null 调用singletonsCurrentlyInDestruction判断该bean是否正在被销毁,如果是则抛出异常。 调用beforeSingletonCreation,进行一些简短的验证:是否正在被创建,是否被忽略 创建需要被吞掉的异常集合,这些异常可以被吞掉。 调用lambda表达式创建的实例beanFactory。调用createBean方法,如果发生异常,则会销毁创建的失败的bean。 调用resolveBeanClass方法,解析bean的class 如果class为null,根据已有的beanDefinition创建新的待使用的beanDefinition,并设置bean的class 调用prepareMethodOverrides,覆盖要被重写的方法。这里不细致查看该方法了。 调用resolveBeforeInstantiation方法,使用beanFactory中的BeanPostProcessors去生成bean。 首先根据beanDefinition中的beforeInstantiationResolved,判断是否已经调用过该方法。如果已经调用,则不再调用 如果beanDefinition不是Synthetic的,且当前beanFactory中有InstantiationAwareBeanPostProcessors 调用determineTargetType获取bean的type。 bean的type不是null的情况,调用applyBeanPostProcessorsBeforeInstantiation方法。 遍历beanFactoryProcessor让所有是InstantiationAwareBeanPostProcessor实例的beanFactoryProcessor,执行postProcessBeforeInstantiation方法。 如果有哪个beanFactoryProcessor,创建了bean,则结束循环,返回bean的实例。 对于AspectJAwareAdvisorAutoProxyCreator来说主要为: 调用getCacheKey获取key,相当于对id做了变形。 如果bean的id有值,或者targetSourcedBeans不包含bean的id 如果advisedBeans包含该key,返回null 如果是Advice,Pointcut,Advisor,AopInfrastructureBean的实例或者是original的实例,把key放入advisedBeans,并返回null。 获取调用getCustomTargetSource获取自定义的代理,如果获取代理为null,返回null,否则调用自定义的代理进行处理 如果此时,bean不为null,则调用applyBeanPostProcessorsAfterInitialization方法。 遍历beanFactoryProcessor,执行遍历beanFactoryProcessor的postProcessBeforeInstantiation方法。后置处理bean的初始化。。。 如果此时生成的bean不为null则直接返回bean。 调用doCreateBean方法,创建bean,并返回bean。 设置newSingleton为true 调用afterSingletonCreation,进行一些简短的验证:是否移除正在被创建成功,是否被忽略 调用addSingleton方法,创建的实例放入singletonObjects,bean的id放入registeredSingletons 返回创建的bean。
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); } beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { // Has the singleton object implicitly appeared in the meantime -> // if yes, proceed with it since the exception indicates that state. singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } afterSingletonCreation(beanName); } if (newSingleton) { addSingleton(beanName, singletonObject); } } return singletonObject; } }
/** * Central method of this class: creates a bean instance, * populates the bean instance, applies post-processors, etc. * @see #doCreateBean */ @Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isTraceEnabled()) { logger.trace("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and // clone the bean definition in case of a dynamically resolved Class // which cannot be stored in the shared merged bean definition. Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // A previously detected exception with proper bean creation context already, // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } }
4.10.4 doCreateBean
如果bean是单例的,从factoryBeanInstanceCache移除该bean 调用createBeanInstance方法创建bean的实例,以及bean的包装类 调用resolveBeanClass获取bean的class 验证class,没通过则抛出异常。 获取instanceSupplier,如果instanceSupplier不为null,调用obtainFromSupplier方法,优先从instanceSupplier方法中获取bean的实例。不细看了。 获取工厂方法的名称,如果过长方法的名称不为null,调用instantiateUsingFactoryMethod方法,优先从工厂方法中获取的bean的实例,不惜看了。 如果已经创建过bean了。需要autowire直接调用autowireConstructor返回,否则调用instantiateBean返回,这两个方法放在后面说明。 调用determineCandidateConstructors方法获取,获取构造函数。如果构造函数不为null或者autowireMode为构造函数,或者有构造函数的参数,或者显示参数不为null,调用autowireConstructor构造实例。 遍历beanFactoryProcessor让所有是SmartInstantiationAwareBeanPostProcessor实例的beanFactoryProcessor,执行determineCandidateConstructors方法。 获取期望使用的构造函数,如果期望的构造函数不为null,调用autowireConstructor进行构造。 进行一系列的构造函数处理之后,找到想要的构造函数,通过ConstructorResolver进行实例化。内部和instantiateBean方法类似 调用instantiateBean进行初始化。 获取默认的实例化策略。一般为CglibSubclassingInstantiationStrategy,然后通过反射,通过无参数的构造函数创建对象。 创建bean的包装。 调用initBeanWrapper初始化包装类。一为设置转化服务类。二为调用registerCustomEditors,注册自定义的编辑。 设置beanDefinition的resolvedTargetType 调用applyMergedBeanDefinitionPostProcessors。并设置postProcessed为true 遍历beanFactoryProcessor让所有是MergedBeanDefinitionPostProcessor实例的beanFactoryProcessor,执行postProcessMergedBeanDefinition方法。 调用addSingletonFactory方法,放入singletonFactories,和registeredSingletons 调用populateBean方法,这个方法主要是为属性进行设置。对于ref的bean会先从缓存中获取,如果没有则会递归调用getBean方法,进行创建,并注册依赖。 该方法允许实现了InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation的方法的factoryBeanProcessor先处理,并直接返回处理的结果。 该方法允许实现了InstantiationAwareBeanPostProcessor的postProcessProperties的方法的factoryBeanProcessor先处理,并直接返回处理的结果。 对于需要进行依赖检查的,调用checkDependencies方法进行依赖检查。 最后调用applyPropertyValues方法,通过反射为属性进行设值。 该方法的主要功能是:通过BeanDefinitionValueResolver的resolveValueIfNecessary进行解析之前在创建beanDefinition时,包装好的属性。 针对不同的属性调用不同的方法。对于RuntimeBeanReference类型的属性,会从beanFactory及其父beanFactory中寻找已经创建好的,如果有会直接返回,如果没有则会递归调用getBean方法,进行创建,并注册依赖。 调用initializeBean方法,主要是对bean进行初始化,包括调用初始化方法,和afterPropertiesSet 该方法允许实现了BeanPostProcessor的postProcessBeforeInitialization的方法的factoryBeanProcessor先处理 在调用invokeInitMethods方法, 先调用bean的afterPropertiesSet方法进行属性设置完成的进一步自定义处理。 然后在调用自定义的初始化方法进行初始化。 该方法允许实现了BeanPostProcessor的postProcessAfterInitialization的方法的factoryBeanProcessor进一步处理。 对于AspectJAwareAdvisorAutoProxyCreator来说,如果该bean需要被代理的话。就会代理该类,他会根据情况选择使用cglib或者是使用jdk进行代理。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } 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.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); 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<>(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 " + "'getBeanNamesForType' 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); } return exposedObject; }
/** * 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 explicit arguments to use for constructor or factory method invocation * @return a BeanWrapper for the new instance * @see #obtainFromSupplier * @see #instantiateUsingFactoryMethod * @see #autowireConstructor * @see #instantiateBean */ protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable 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()); } Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName); } if (mbd.getFactoryMethodName() != null) { 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); } } // Candidate constructors for autowiring? Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } // Preferred constructors for default construction? ctors = mbd.getPreferredConstructors(); if (ctors != null) { return autowireConstructor(beanName, mbd, ctors, null); } // No special handling: simply use no-arg constructor. return instantiateBean(beanName, mbd); }
/** * Instantiate the given bean using its default constructor. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @return a BeanWrapper for the new instance */ protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) { try { Object beanInstance; if (System.getSecurityManager() != null) { beanInstance = AccessController.doPrivileged( (PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this), getAccessControlContext()); } else { beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this); } BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw; } catch (Throwable ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); } }
设置属性
/** * 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 the BeanWrapper with bean instance */ @SuppressWarnings("deprecation") // for postProcessPropertyValues protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (bw == null) { if (mbd.hasPropertyValues()) { 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. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } } PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }
/** * Apply the given property values, resolving any runtime references * to other beans in this bean factory. Must use deep copy, so we * don't permanently modify this property. * @param beanName the bean name passed for better exception information * @param mbd the merged bean definition * @param bw the BeanWrapper wrapping the target object * @param pvs the new property values */ protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { if (pvs.isEmpty()) { return; } if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) { ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext()); } MutablePropertyValues mpvs = null; List<PropertyValue> original; if (pvs instanceof MutablePropertyValues) { mpvs = (MutablePropertyValues) pvs; if (mpvs.isConverted()) { // Shortcut: use the pre-converted values as-is. try { bw.setPropertyValues(mpvs); return; } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } } original = mpvs.getPropertyValueList(); } else { original = Arrays.asList(pvs.getPropertyValues()); } TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); // Create a deep copy, resolving any references for values. List<PropertyValue> deepCopy = new ArrayList<>(original.size()); boolean resolveNecessary = false; for (PropertyValue pv : original) { if (pv.isConverted()) { deepCopy.add(pv); } else { String propertyName = pv.getName(); Object originalValue = pv.getValue(); if (originalValue == AutowiredPropertyMarker.INSTANCE) { Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod(); if (writeMethod == null) { throw new IllegalArgumentException("Autowire marker for property without write method: " + pv); } originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true); } Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); Object convertedValue = resolvedValue; boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); if (convertible) { convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); } // Possibly store converted value in merged bean definition, // in order to avoid re-conversion for every created bean instance. if (resolvedValue == originalValue) { if (convertible) { pv.setConvertedValue(convertedValue); } deepCopy.add(pv); } else if (convertible && originalValue instanceof TypedStringValue && !((TypedStringValue) originalValue).isDynamic() && !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) { pv.setConvertedValue(convertedValue); deepCopy.add(pv); } else { resolveNecessary = true; deepCopy.add(new PropertyValue(pv, convertedValue)); } } } if (mpvs != null && !resolveNecessary) { mpvs.setConverted(); } // Set our (possibly massaged) deep copy. try { bw.setPropertyValues(new MutablePropertyValues(deepCopy)); } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } }
/** * Given a PropertyValue, return a value, resolving any references to other * beans in the factory if necessary. The value could be: * <li>A BeanDefinition, which leads to the creation of a corresponding * new bean instance. Singleton flags and names of such "inner beans" * are always ignored: Inner beans are anonymous prototypes. * <li>A RuntimeBeanReference, which must be resolved. * <li>A ManagedList. This is a special collection that may contain * RuntimeBeanReferences or Collections that will need to be resolved. * <li>A ManagedSet. May also contain RuntimeBeanReferences or * Collections that will need to be resolved. * <li>A ManagedMap. In this case the value may be a RuntimeBeanReference * or Collection that will need to be resolved. * <li>An ordinary object or {@code null}, in which case it's left alone. * @param argName the name of the argument that the value is defined for * @param value the value object to resolve * @return the resolved object */ @Nullable public Object resolveValueIfNecessary(Object argName, @Nullable Object value) { // We must check each value to see whether it requires a runtime reference // to another bean to be resolved. if (value instanceof RuntimeBeanReference) { RuntimeBeanReference ref = (RuntimeBeanReference) value; return resolveReference(argName, ref); } else if (value instanceof RuntimeBeanNameReference) { String refName = ((RuntimeBeanNameReference) value).getBeanName(); refName = String.valueOf(doEvaluate(refName)); if (!this.beanFactory.containsBean(refName)) { throw new BeanDefinitionStoreException( "Invalid bean name '" + refName + "' in bean reference for " + argName); } return refName; } else if (value instanceof BeanDefinitionHolder) { // Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases. BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value; return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition()); } else if (value instanceof BeanDefinition) { // Resolve plain BeanDefinition, without contained name: use dummy name. BeanDefinition bd = (BeanDefinition) value; String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(bd); return resolveInnerBean(argName, innerBeanName, bd); } else if (value instanceof DependencyDescriptor) { Set<String> autowiredBeanNames = new LinkedHashSet<>(4); Object result = this.beanFactory.resolveDependency( (DependencyDescriptor) value, this.beanName, autowiredBeanNames, this.typeConverter); for (String autowiredBeanName : autowiredBeanNames) { if (this.beanFactory.containsBean(autowiredBeanName)) { this.beanFactory.registerDependentBean(autowiredBeanName, this.beanName); } } return result; } else if (value instanceof ManagedArray) { // May need to resolve contained runtime references. ManagedArray array = (ManagedArray) value; Class<?> elementType = array.resolvedElementType; if (elementType == null) { String elementTypeName = array.getElementTypeName(); if (StringUtils.hasText(elementTypeName)) { try { elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader()); array.resolvedElementType = elementType; } catch (Throwable ex) { // Improve the message by showing the context. throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Error resolving array type for " + argName, ex); } } else { elementType = Object.class; } } return resolveManagedArray(argName, (List<?>) value, elementType); } else if (value instanceof ManagedList) { // May need to resolve contained runtime references. return resolveManagedList(argName, (List<?>) value); } else if (value instanceof ManagedSet) { // May need to resolve contained runtime references. return resolveManagedSet(argName, (Set<?>) value); } else if (value instanceof ManagedMap) { // May need to resolve contained runtime references. return resolveManagedMap(argName, (Map<?, ?>) value); } else if (value instanceof ManagedProperties) { Properties original = (Properties) value; Properties copy = new Properties(); original.forEach((propKey, propValue) -> { if (propKey instanceof TypedStringValue) { propKey = evaluate((TypedStringValue) propKey); } if (propValue instanceof TypedStringValue) { propValue = evaluate((TypedStringValue) propValue); } if (propKey == null || propValue == null) { throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Error converting Properties key/value pair for " + argName + ": resolved to null"); } copy.put(propKey, propValue); }); return copy; } else if (value instanceof TypedStringValue) { // Convert value to target type here. TypedStringValue typedStringValue = (TypedStringValue) value; Object valueObject = evaluate(typedStringValue); try { Class<?> resolvedTargetType = resolveTargetType(typedStringValue); if (resolvedTargetType != null) { return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType); } else { return valueObject; } } catch (Throwable ex) { // Improve the message by showing the context. throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Error converting typed String value for " + argName, ex); } } else if (value instanceof NullBean) { return null; } else { return evaluate(value); } }
/** * Resolve a reference to another bean in the factory. */ @Nullable private Object resolveReference(Object argName, RuntimeBeanReference ref) { try { Object bean; Class<?> beanType = ref.getBeanType(); if (ref.isToParent()) { BeanFactory parent = this.beanFactory.getParentBeanFactory(); if (parent == null) { throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean " + ref + " in parent factory: no parent factory available"); } if (beanType != null) { bean = parent.getBean(beanType); } else { bean = parent.getBean(String.valueOf(doEvaluate(ref.getBeanName()))); } } else { String resolvedName; if (beanType != null) { NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType); bean = namedBean.getBeanInstance(); resolvedName = namedBean.getBeanName(); } else { resolvedName = String.valueOf(doEvaluate(ref.getBeanName())); bean = this.beanFactory.getBean(resolvedName); } this.beanFactory.registerDependentBean(resolvedName, this.beanName); } if (bean instanceof NullBean) { bean = null; } return bean; } catch (BeansException ex) { throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex); } }
初始化bean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isTraceEnabled()) { logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { ((InitializingBean) bean).afterPropertiesSet(); return null; }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { ((InitializingBean) bean).afterPropertiesSet(); } } if (mbd != null && bean.getClass() != NullBean.class) { String initMethodName = mbd.getInitMethodName(); if (StringUtils.hasLength(initMethodName) && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { invokeCustomInitMethod(beanName, bean, mbd); } } }
bean初始化以后,aop拦截,创建代理实例
/** * Create a proxy with the configured interceptors if the bean is * identified as one to proxy by the subclass. * @see #getAdvicesAndAdvisorsForBean */ @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; }
/** * Wrap the given bean if necessary, i.e. if it is eligible for being proxied. * @param bean the raw bean instance * @param beanName the name of the bean * @param cacheKey the cache key for metadata access * @return a proxy wrapping the bean, or the raw bean instance as-is */ 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()); }
4.10.5 getObjectForBeanInstance
最后调用getObjectForBeanInstance,创建class为factoryBean的bean。 调用BeanFactoryUtils.isFactoryDereference判断id是带有factoryBean前缀的 如果是NullBean的实例,直接返回该bean 如果不是FactoryBean的实例,抛出异常 设置beanDefinition的FactoryBean为true 返回该bean 如果bean不是FactoryBean的实例,直接返回该bean 尝试从缓存中factoryBeanObjectCache获取bean的实例 缓存中不存在时调用getObjectFromFactoryBean获取,过程主要是调用factoryBean的getObject获取bean,并存入缓存,并可以支持BeanPostProcessors的postProcessAfterInitialization方法。
@Override protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { String currentlyCreatedBean = this.currentlyCreatedBean.get(); if (currentlyCreatedBean != null) { registerDependentBean(beanName, currentlyCreatedBean); } return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd); }
protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { // Don't let calling code try to dereference the factory if the bean isn't a factory. if (BeanFactoryUtils.isFactoryDereference(name)) { if (beanInstance instanceof NullBean) { return beanInstance; } if (!(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass()); } if (mbd != null) { mbd.isFactoryBean = true; } return beanInstance; } // Now we have the bean instance, which may be a normal bean or a FactoryBean. // If it's a FactoryBean, we use it to create a bean instance, unless the // caller actually wants a reference to the factory. if (!(beanInstance instanceof FactoryBean)) { return beanInstance; } Object object = null; if (mbd != null) { mbd.isFactoryBean = true; } else { object = getCachedObjectForFactoryBean(beanName); } if (object == null) { // Return bean instance from factory. FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // Caches object obtained from FactoryBean if it is a singleton. if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }
4.5 finishRefresh
发布beanFactory容器启动事件。
调用clearResourceCaches,请资源的缓存 调用initLifecycleProcessor创建初始化注册DefaultLifecycleProcessor 调用publishEvent发布ContextRefreshedEvent事件 调用LiveBeansView.registerApplicationContext注册Mbean
protected void finishRefresh() { // Clear context-level resource caches (such as ASM metadata from scanning). clearResourceCaches(); // Initialize lifecycle processor for this context. initLifecycleProcessor(); // Propagate refresh to lifecycle processor first. getLifecycleProcessor().onRefresh(); // Publish the final event. publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active. LiveBeansView.registerApplicationContext(this); }
这篇关于spring5源码阅读2spring容器启动的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南