diff --git a/README.md b/README.md index d2443b6..b10353b 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ ### AOP - [AOP 源码实现及分析](/docs/Spring/AOP/AOP源码实现及分析.md) - [JDK 动态代理的实现原理解析](/docs/Spring/AOP/JDK动态代理的实现原理解析.md) +- [Spring AOP 如何生效(Spring AOP标签解析)](/docs/Spring/AOP/Spring-Aop如何生效.md) ### SpringMVC - [温习一下servlet](/docs/Spring/SpringMVC/温习一下servlet.md) @@ -37,6 +38,17 @@ ### Spring源码故事(瞎编版) - [面筋哥 IoC 容器的一天(上)](/docs/Spring/Spring源码故事(瞎编版)/面筋哥IoC容器的一天(上).md) +### Spring 类解析 +- [Spring 自定义标签解析](/docs/Spring/clazz/Spring-自定义标签解析.md) +- [Spring Scan 包扫描](/docs/Spring/clazz/Spring-scan.md) +- [Spring 注解工具类](/docs/Spring/clazz/Spring-AnnotationUtils.md) +- [Spring 别名注册](/docs/Spring/clazz/Spring-SimpleAliasRegistry.md) +- [Spring 标签解析类](/docs/Spring/clazz/Spring-BeanDefinitionParserDelegate.md) + +### Spring5 新特性 +- [Spring5-spring.components解析](/docs/Spring/Spring5新特性/Spring-spring-components.md) + + ## MyBatis ### 基础支持层 - [反射工具箱和TypeHandler系列](docs/Mybatis/基础支持层/1、反射工具箱和TypeHandler系列.md) @@ -50,6 +62,23 @@ - [StatementHandler](docs/Mybatis/核心处理层/4、StatementHandler.md) - [Executor组件](docs/Mybatis/核心处理层/5、Executor组件.md) - [SqlSession组件](docs/Mybatis/核心处理层/6、SqlSession组件.md) +### 类解析 +- [Mybatis-Cache](/docs/Mybatis/基础支持层/Mybatis-Cache.md) +- [Mybatis-log](/docs/Mybatis/基础支持层/Mybatis-log.md) +- [Mybatis-Reflector](/docs/Mybatis/基础支持层/Mybatis-Reflector.md) +- [Mybatis-Alias](/docs/Mybatis/核心处理层/Mybatis-Alias.md) +- [Mybatis-Cursor](/docs/Mybatis/核心处理层/Mybatis-Cursor.md) +- [Mybatis-DataSource](/docs/Mybatis/核心处理层/Mybatis-DataSource.md) +- [Mybatis-DyanmicSqlSourcce](/docs/Mybatis/核心处理层/Mybatis-DyanmicSqlSourcce.md) +- [Mybatis-MapperMethod](/docs/Mybatis/核心处理层/Mybatis-MapperMethod.md) +- [Mybatis-MetaObject](/docs/Mybatis/核心处理层/Mybatis-MetaObject.md) +- [Mybatis-MethodSignature](/docs/Mybatis/核心处理层/Mybatis-MethodSignature.md) +- [Mybatis-ObjectWrapper](/docs/Mybatis/核心处理层/Mybatis-ObjectWrapper.md) +- [Mybatis-ParamNameResolver](/docs/Mybatis/核心处理层/Mybatis-ParamNameResolver.md) +- [Mybatis-SqlCommand](/docs/Mybatis/核心处理层/Mybatis-SqlCommand.md) +- [Mybats-GenericTokenParser](/docs/Mybatis/核心处理层/Mybats-GenericTokenParser.md) + + ## Netty ### IO - [把被说烂的BIO、NIO、AIO再从头到尾扯一遍](docs/Netty/IO/把被说烂的BIO、NIO、AIO再从头到尾扯一遍.md) diff --git a/docs/Spring/AOP/Spring-Aop如何生效.md b/docs/Spring/AOP/Spring-Aop如何生效.md new file mode 100644 index 0000000..c29b1b6 --- /dev/null +++ b/docs/Spring/AOP/Spring-Aop如何生效.md @@ -0,0 +1,141 @@ +# Spring AOP 如何生效 +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) + +## 解析 +- 在使用 Spring AOP 技术的时候会有下面这段代码在xml配置文件中出现,来达到 Spring 支持 AOP +```xml + +``` +- 源码阅读目标找到了,那么怎么去找入口或者对这句话的标签解析方法呢?项目中使用搜索 + +  + + 这样就找到了具体解析方法了 + +### `org.springframework.aop.config.AspectJAutoProxyBeanDefinitionParser` + +- 类图 + + +```java + @Override + @Nullable + public BeanDefinition parse(Element element, ParserContext parserContext) { + // 注册 + AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); + // 子类解析 + extendBeanDefinition(element, parserContext); + return null; + } + +``` + +```java + /** + * 注册 + * @param parserContext + * @param sourceElement + */ + public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary( + ParserContext parserContext, Element sourceElement) { + + // 注册或者升级bean + BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary( + parserContext.getRegistry(), parserContext.extractSource(sourceElement)); + // proxy-target-class 和 expose-proxy 标签处理 + useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); + // 注册组件并且交给监听器 + registerComponentIfNecessary(beanDefinition, parserContext); + } + +``` +- `org.springframework.aop.config.AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)` +```java + @Nullable + public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary( + BeanDefinitionRegistry registry, @Nullable Object source) { + + // 注册或者升级 AspectJ + return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); + } + +``` +- `org.springframework.aop.config.AopConfigUtils.registerOrEscalateApcAsRequired` +```java + /** + * 注册或者升级 bean + * @param cls 类 + * @param registry 注册器 + * @param source 源类 + * @return + */ + @Nullable + private static BeanDefinition registerOrEscalateApcAsRequired( + Class> cls, BeanDefinitionRegistry registry, @Nullable Object source) { + + Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); + + // 判断注册器是否包含org.springframework.aop.config.internalAutoProxyCreator + if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { + // 获取注册器 + BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); + // 创建新的bean对象 + if (!cls.getName().equals(apcDefinition.getBeanClassName())) { + int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); + int requiredPriority = findPriorityForClass(cls); + if (currentPriority < requiredPriority) { + apcDefinition.setBeanClassName(cls.getName()); + } + } + // 即将创建的Bean对象和当前的注册器相同返回null + return null; + } + + RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); + beanDefinition.setSource(source); + // 设置加载顺序 + beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); + beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + // 注册bean定义 + registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); + return beanDefinition; + } + +``` +### org.springframework.aop.config.AopNamespaceUtils.useClassProxyingIfNecessary +```java + /** + * proxy-target-class 和 expose-proxy 标签处理 + */ + private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) { + if (sourceElement != null) { + // 处理 proxy-target-class + boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE)); + if (proxyTargetClass) { + AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); + } + // 处理 expose-proxy + boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE)); + if (exposeProxy) { + AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); + } + } + } + +``` +- `org.springframework.aop.config.AopConfigUtils.forceAutoProxyCreatorToUseClassProxying` +```java + public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) { + if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { + BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); + definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE); + } + } + +``` +- `forceAutoProxyCreatorToExposeProxy`方法就不贴出代码了,操作和`forceAutoProxyCreatorToUseClassProxying`一样都是将读取到的数据放入bean对象作为一个属性存储 + + +## 总结 +- 实现`org.springframework.beans.factory.xml.BeanDefinitionParser`接口的类,多用于对xml标签的解析,并且入口为`parse`方法,如果是一个bean对象通常会和Spring监听器一起出现 \ No newline at end of file diff --git a/docs/Spring/IoC/Spring-自定义标签解析.md b/docs/Spring/IoC/Spring-自定义标签解析.md new file mode 100644 index 0000000..e4520d7 --- /dev/null +++ b/docs/Spring/IoC/Spring-自定义标签解析.md @@ -0,0 +1,658 @@ +# Spring 自定义标签解析 +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework) +- 与自定义标签解析相关的类 + 1. `org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser` + 2. `org.springframework.beans.factory.xml.NamespaceHandlerSupport` + +- 开始源码之前先搭建一个环境 + + +## 环境搭建 +- 创建对象 +```java +public class UserXtd { + private String userName; + private String emailAddress; + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getEmailAddress() { + return emailAddress; + } + + public void setEmailAddress(String emailAddress) { + this.emailAddress = emailAddress; + } +} +``` +- 创建 xsd 文件 +```xml + + + + + + + + + + + +``` +- 创建 namespaceHandler +```java +public class UserNamespaceHandler extends NamespaceHandlerSupport { + @Override + public void init() { + registerBeanDefinitionParser("myUser", new UserBeanDefinitionParser()); + } +} +``` +- 创建 beanDefinitionParser +```java +public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { + /** + * 标签对应class + * @param element the {@code Element} that is being parsed + * @return + */ + @Override + protected Class> getBeanClass(Element element) { + return UserXtd.class; + } + + + @Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + // 获取 userName 标签属性值 + String name = element.getAttribute("userName"); + // 获取 emailAddress 标签属性值 + String address = element.getAttribute("emailAddress"); + + if (StringUtils.hasText(name)) { + builder.addPropertyValue("userName", name); + } + if (StringUtils.hasText(address)) { + builder.addPropertyValue("emailAddress", address); + } + } +} + +``` +- 创建 resource/META-INF/spring.handlers +```text +http\://www.huifer.com/schema/user=com.huifer.source.spring.parser.UserNamespaceHandler +``` +- 创建 resource/META-INF/spring.schemas +```text +http\://www.huifer.com/schema/user.xsd=META-INF/spring-test.xsd +``` +- 创建测试用例xml +```xml + + + + + + +``` +- 创建 Java 运行方法 +```java +/** + * 自定义标签测试用例 + */ +public class XSDDemo { + public static void main(String[] args) { + ApplicationContext applicationContext = new ClassPathXmlApplicationContext("XTD-xml.xml"); + UserXtd user = (UserXtd) applicationContext.getBean("testUserBean"); + System.out.println(user.getEmailAddress()); + } +} +``` +- 这里我们希望输出结果是`huifer97@163.com`,运行后结果也确实是`huifer97@163.com` + +## 解析 DefaultNamespaceHandlerResolver +- 入口方法`org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions` +```java + 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 { + // 非spring 默认标签解析 + delegate.parseCustomElement(ele); + } + } + } + } + else { + delegate.parseCustomElement(root); + } + } + +``` +- 调用链路 +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(org.w3c.dom.Element)` + - `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)` + +```java + /** + * Parse a custom element (outside of the default namespace). + *
+ * 自定义标签解析 + * + * @param ele the element to parse + * @param containingBd the containing bean definition (if any) + * @return the resulting bean definition + */ + @Nullable + 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)); + } + +``` + + + +- `http://www.huifer.com/schema/user`和我们定义的xsd文件中的url相同,如何找到对应的NamespaceHandler,在`META-INF/spring.handlers`中有定义, + + `http\://www.huifer.com/schema/user=com.huifer.source.spring.parser.UserNamespaceHandler` + + `NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);`这行代码就是获取`spring.handlers`中的定义 + +- 处理方法`org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve` + + + +```java + /** + * Locate the {@link NamespaceHandler} for the supplied namespace URI + * from the configured mappings. + * + * 根据 namespaceUri 获取对应的 {@link NamespaceHandler} + * @param namespaceUri the relevant namespace URI + * @return the located {@link NamespaceHandler}, or {@code null} if none found + */ + @Override + @Nullable + public NamespaceHandler resolve(String namespaceUri) { + // 获取handlerMapping + Map handlerMappings = getHandlerMappings(); + // 从 handlerMapping 中获取类名 + 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); + // 调用init()方法,自定义类中实现 + namespaceHandler.init(); + // 放入缓存 + handlerMappings.put(namespaceUri, namespaceHandler); + // 返回自定义的 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); + } + } + } + +``` + + + +- `org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#getHandlerMappings`跟踪这个方法 + +```JAVA + /** + * Load the specified NamespaceHandler mappings lazily. + * + * 获取handlerMappings + */ + private Map getHandlerMappings() { + Map handlerMappings = this.handlerMappings; + } +``` + + + + + +- 这里直接存在数据了,他是从什么时候加载的? + +- `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions` + + 这个方法在注册bean定义的时候调用 + + ```java + public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { + BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); + int countBefore = getRegistry().getBeanDefinitionCount(); + // 注册方法 + // createReaderContext 初始化HandlerMapping + documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); + return getRegistry().getBeanDefinitionCount() - countBefore; + } + + ``` + +- 继续跟踪`createReaderContext` + + ```java + org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createReaderContext + ``` + + ```java + public XmlReaderContext createReaderContext(Resource resource) { + return new XmlReaderContext(resource, this.problemReporter, this.eventListener, + this.sourceExtractor, this, getNamespaceHandlerResolver()); + } + + ``` + +- 继续跟踪`getNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#getNamespaceHandlerResolver` + + ```java + public NamespaceHandlerResolver getNamespaceHandlerResolver() { + if (this.namespaceHandlerResolver == null) { + this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver(); + } + return this.namespaceHandlerResolver; + } + + ``` + +- 继续跟踪`createDefaultNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createDefaultNamespaceHandlerResolver` + + ```java + protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() { + ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader()); + return new DefaultNamespaceHandlerResolver(cl); + } + ``` + + + +- 继续跟踪`DefaultNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver` + + ```java + public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) { + this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); + } + + ``` + + 他回到了我们之前疑问的地方 `handlerMappings` 如何出现的 + + 断点 + +  + + ```JAVA + public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) { + this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); + } + ``` + + `public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";` + +  + + 此时还是空 + + 走完 + +  + + ```java + @Override + public String toString() { + return "NamespaceHandlerResolver using mappings " + getHandlerMappings(); + } + + ``` + + + +```JAVA + /** + * Load the specified NamespaceHandler mappings lazily. + * + * 获取handlerMappings + */ + private Map getHandlerMappings() { + Map handlerMappings = this.handlerMappings; + // 缓存不存在 + if (handlerMappings == null) { + synchronized (this) { + handlerMappings = this.handlerMappings; + if (handlerMappings == null) { + if (logger.isTraceEnabled()) { + logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]"); + } + try { + // 将本地文件读出 + Properties mappings = + PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader); + if (logger.isTraceEnabled()) { + logger.trace("Loaded NamespaceHandler mappings: " + mappings); + } + handlerMappings = new ConcurrentHashMap<>(mappings.size()); + // 转换成map结构 + CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings); + this.handlerMappings = handlerMappings; + } + catch (IOException ex) { + throw new IllegalStateException( + "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex); + } + } + } + } + return handlerMappings; + } + +``` + + + + + + + + + +## org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#resolve + +```java + @Override + @Nullable + public NamespaceHandler resolve(String namespaceUri) { + // 获取handlerMapping + Map handlerMappings = getHandlerMappings(); + // 从 handlerMapping 中获取类名 + 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); + // 调用init()方法,自定义类中实现 + namespaceHandler.init(); + // 放入缓存 + handlerMappings.put(namespaceUri, namespaceHandler); + // 返回自定义的 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); + } + } + } + +``` + +执行`init`方法 + +```java +public class UserNamespaceHandler extends NamespaceHandlerSupport { + @Override + public void init() { + registerBeanDefinitionParser("myUser", new UserBeanDefinitionParser()); + } +} +``` + +```java + /** + * Subclasses can call this to register the supplied {@link BeanDefinitionParser} to + * handle the specified element. The element name is the local (non-namespace qualified) + * name. + * + * 将标签名称,标签解析类放入 + */ + protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) { + this.parsers.put(elementName, parser); + } + +``` + + + +- 方法走完,回到开始的方法 + + ```java + /** + * Parse a custom element (outside of the default namespace). + * + * 自定义标签解析 + * + * @param ele the element to parse + * @param containingBd the containing bean definition (if any) + * @return the resulting bean definition + */ + @Nullable + public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { + // 自定义标签解析 + String namespaceUri = getNamespaceURI(ele); + if (namespaceUri == null) { + return null; + } + // 根据命名空间获取处理类 + // org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve + 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)); + } + + ``` + + + + + + + + + +## org.springframework.beans.factory.xml.NamespaceHandler#parse + +- `org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse` + + ```java + @Override + @Nullable + public BeanDefinition parse(Element element, ParserContext parserContext) { + BeanDefinitionParser parser = findParserForElement(element, parserContext); + return (parser != null ? parser.parse(element, parserContext) : null); + } + + ``` + +### org.springframework.beans.factory.xml.NamespaceHandlerSupport#findParserForElement + +```java + @Nullable + private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { + // 获取标签名称 + String localName = parserContext.getDelegate().getLocalName(element); + // 在map中获取对应的标签解析类 + BeanDefinitionParser parser = this.parsers.get(localName); + // 空报错 + if (parser == null) { + parserContext.getReaderContext().fatal( + "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); + } + // 不为空返回 + return parser; + } + +``` + + + +### org.springframework.beans.factory.xml.BeanDefinitionParser#parse + +- `org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parse` + +```java + public final BeanDefinition parse(Element element, ParserContext parserContext) { + /** + * {@link AbstractSingleBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)} + */ + AbstractBeanDefinition definition = parseInternal(element, parserContext); + + + } +``` + +### org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#parseInternal + +```java +@Override + protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); + String parentName = getParentName(element); + if (parentName != null) { + builder.getRawBeanDefinition().setParentName(parentName); + } + // 调用自己实现的方法 com.huifer.source.spring.parser.UserBeanDefinitionParser.getBeanClass + Class> beanClass = getBeanClass(element); + if (beanClass != null) { + builder.getRawBeanDefinition().setBeanClass(beanClass); + } + else { + // getBeanClassName 同样也是可以在自定义的解析类中实现 + 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. + // 设置scope + builder.setScope(containingBd.getScope()); + } + if (parserContext.isDefaultLazyInit()) { + // Default-lazy-init applies to custom bean definitions as well. + // 设置 lazy-init + builder.setLazyInit(true); + } + + // 执行解析方法,在自定义解析类中存在com.huifer.source.spring.parser.UserBeanDefinitionParser.doParse + doParse(element, parserContext, builder); + return builder.getBeanDefinition(); + } +``` + + + + + +执行`com.huifer.source.spring.parser.UserBeanDefinitionParser#doParse` + +```JAVA +@Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + // 获取 userName 标签属性值 + String name = element.getAttribute("userName"); + // 获取 emailAddress 标签属性值 + String address = element.getAttribute("emailAddress"); + + if (StringUtils.hasText(name)) { + builder.addPropertyValue("userName", name); + } + if (StringUtils.hasText(address)) { + builder.addPropertyValue("emailAddress", address); + } + } +``` + + + + + diff --git a/docs/Spring/JDBC/Spring-jdbc.md b/docs/Spring/JDBC/Spring-jdbc.md new file mode 100644 index 0000000..47b46b3 --- /dev/null +++ b/docs/Spring/JDBC/Spring-jdbc.md @@ -0,0 +1,522 @@ +# Spring JDBC +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) + + + +## 环境搭建 + +- 依赖 + + ```gradle + compile(project(":spring-jdbc")) + compile group: 'com.alibaba', name: 'druid', version: '1.1.21' + compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.47' + ``` + +- db配置 + + ```properties + jdbc.url= + jdbc.driverClass= + jdbc.username= + jdbc.password= + ``` + +- 实体对象 + + ```JAVA + public class HsLog { + private Integer id; + + private String source; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + } + ``` + + + +- DAO + + ```JAVA + public interface HsLogDao { + List findAll(); + + void save(HsLog hsLog); + } + + ``` + + + +- 实现类 + + ```JAVA + public class HsLogDaoImpl extends JdbcDaoSupport implements HsLogDao { + + + @Override + public List findAll() { + return this.getJdbcTemplate().query("select * from hs_log", new HsLogRowMapper()); + + } + + @Override + public void save(HsLog hsLog) { + this.getJdbcTemplate().update("insert into hs_log (SOURCE) values(?)" + , new Object[]{ + hsLog.getSource(), + } + + ); + } + + class HsLogRowMapper implements RowMapper { + + public HsLog mapRow(ResultSet rs, int rowNum) throws SQLException { + + HsLog log = new HsLog(); + log.setId(rs.getInt("id")); + log.setSource(rs.getString("source")); + return log; + } + + } + } + + ``` + + + +- xml + + ```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ``` + +- 运行方法 + + ```JAVA + + public class SpringJDBCSourceCode { + public static void main(String[] args) { + ApplicationContext applicationContext = new ClassPathXmlApplicationContext("JDBC-demo.xml"); + HsLogDaoImpl bean = applicationContext.getBean(HsLogDaoImpl.class); + System.out.println(bean.findAll()); + HsLog hsLog = new HsLog(); + hsLog.setSource("jlkjll"); + bean.save(hsLog); + + } + } + + ``` + + + + + + + +## 链接对象构造 + +`Connection con = DataSourceUtils.getConnection(obtainDataSource());` + +```java + public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException { + try { + return doGetConnection(dataSource); + } + catch (SQLException ex) { + throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection", ex); + } + catch (IllegalStateException ex) { + throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection: " + ex.getMessage()); + } + } + +``` + +### org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection + +```java + public static Connection doGetConnection(DataSource dataSource) throws SQLException { + Assert.notNull(dataSource, "No DataSource specified"); + + ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource); + if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) { + conHolder.requested(); + if (!conHolder.hasConnection()) { + logger.debug("Fetching resumed JDBC Connection from DataSource"); + // 设置连接对象 + conHolder.setConnection(fetchConnection(dataSource)); + } + return conHolder.getConnection(); + } + // Else we either got no holder or an empty thread-bound holder here. + + logger.debug("Fetching JDBC Connection from DataSource"); + // 获取链接 + Connection con = fetchConnection(dataSource); + + // 当前线程支持同步 + if (TransactionSynchronizationManager.isSynchronizationActive()) { + try { + // Use same Connection for further JDBC actions within the transaction. + // Thread-bound object will get removed by synchronization at transaction completion. + // 在同一个事物中使用同一个链接对象 + ConnectionHolder holderToUse = conHolder; + if (holderToUse == null) { + holderToUse = new ConnectionHolder(con); + } + else { + holderToUse.setConnection(con); + } + // 记录链接数量 + holderToUse.requested(); + TransactionSynchronizationManager.registerSynchronization( + new ConnectionSynchronization(holderToUse, dataSource)); + holderToUse.setSynchronizedWithTransaction(true); + if (holderToUse != conHolder) { + TransactionSynchronizationManager.bindResource(dataSource, holderToUse); + } + } + catch (RuntimeException ex) { + // Unexpected exception from external delegation call -> close Connection and rethrow. + releaseConnection(con, dataSource); + throw ex; + } + } + + return con; + } + +``` + + + + + +## 释放资源 + +`releaseConnection(con, dataSource);` + +- `org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection` + +```JAVA + public static void releaseConnection(@Nullable Connection con, @Nullable DataSource dataSource) { + try { + doReleaseConnection(con, dataSource); + } + catch (SQLException ex) { + logger.debug("Could not close JDBC Connection", ex); + } + catch (Throwable ex) { + logger.debug("Unexpected exception on closing JDBC Connection", ex); + } + } + +``` + +```java +public static void doReleaseConnection(@Nullable Connection con, @Nullable DataSource dataSource) throws SQLException { + if (con == null) { + return; + } + if (dataSource != null) { + ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource); + if (conHolder != null && connectionEquals(conHolder, con)) { + // It's the transactional Connection: Don't close it. + // 连接数-1 + conHolder.released(); + return; + } + } + // 处理其他情况 + doCloseConnection(con, dataSource); + } +``` + + + + + +### org.springframework.transaction.support.ResourceHolderSupport + +链接数 + +```JAVA + /** + * Increase the reference count by one because the holder has been requested + * (i.e. someone requested the resource held by it). + */ + public void requested() { + this.referenceCount++; + } + + /** + * Decrease the reference count by one because the holder has been released + * (i.e. someone released the resource held by it). + */ + public void released() { + this.referenceCount--; + } +``` + + + + + + + +## 查询解析 + +### org.springframework.jdbc.core.JdbcTemplate + +```XML + + + + +``` +- 从配置中可以知道 JdbcTemplate 需要 dataSource 属性, 就从这里开始讲起 +- `org.springframework.jdbc.support.JdbcAccessor.setDataSource`, 这段代码就只做了赋值操作(依赖注入) +```java +public void setDataSource(@Nullable DataSource dataSource) { + this.dataSource = dataSource; + } +``` +- 下面`hsLogDao`也是依赖注入本篇不做详细讲述。 + + + +### org.springframework.jdbc.core.JdbcTemplate#query(java.lang.String, org.springframework.jdbc.core.RowMapper) + +```java + @Override + public List findAll() { + return this.getJdbcTemplate().query("select * from hs_log", new HsLogRowMapper()); + } + +``` + +```java + @Override + @Nullable + public T query(final String sql, final ResultSetExtractor rse) throws DataAccessException { + Assert.notNull(sql, "SQL must not be null"); + Assert.notNull(rse, "ResultSetExtractor must not be null"); + if (logger.isDebugEnabled()) { + logger.debug("Executing SQL query [" + sql + "]"); + } + + /** + * Callback to execute the query. + */ + class QueryStatementCallback implements StatementCallback, SqlProvider { + @Override + @Nullable + public T doInStatement(Statement stmt) throws SQLException { + ResultSet rs = null; + try { + // 执行sql + rs = stmt.executeQuery(sql); + // 1. org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData + return rse.extractData(rs); + } + finally { + JdbcUtils.closeResultSet(rs); + } + } + + @Override + public String getSql() { + return sql; + } + } + + return execute(new QueryStatementCallback()); + } + +``` + +```java + @Override + @Nullable + public T execute(StatementCallback action) throws DataAccessException { + Assert.notNull(action, "Callback object must not be null"); + + Connection con = DataSourceUtils.getConnection(obtainDataSource()); + Statement stmt = null; + try { + stmt = con.createStatement(); + applyStatementSettings(stmt); + // 执行 + T result = action.doInStatement(stmt); + handleWarnings(stmt); + return result; + } + catch (SQLException ex) { + // Release Connection early, to avoid potential connection pool deadlock + // in the case when the exception translator hasn't been initialized yet. + String sql = getSql(action); + JdbcUtils.closeStatement(stmt); + stmt = null; + DataSourceUtils.releaseConnection(con, getDataSource()); + con = null; + throw translateException("StatementCallback", sql, ex); + } + finally { + JdbcUtils.closeStatement(stmt); + DataSourceUtils.releaseConnection(con, getDataSource()); + } + } +``` + +```JAVA + @Override + public List extractData(ResultSet rs) throws SQLException { + List results = (this.rowsExpected > 0 ? new ArrayList<>(this.rowsExpected) : new ArrayList<>()); + int rowNum = 0; + while (rs.next()) { + // 调用自定义的 rowMapper 进行数据处理 + T t = this.rowMapper.mapRow(rs, rowNum++); + results.add(t); + } + return results; + } + +``` + + + +这样就可以获取到了 + +方法`result`没有什么操作直接返回即可 + +```java + private static T result(@Nullable T result) { + Assert.state(result != null, "No result"); + return result; + } +``` + + + + + + + +## 插入解析 + +```java +@Override + public void save(HsLog hsLog) { + this.getJdbcTemplate().update("insert into hs_log (SOURCE) values(?)" + , new Object[]{ + hsLog.getSource(), + } + + ); + } +``` + +`org.springframework.jdbc.core.JdbcTemplate#update(org.springframework.jdbc.core.PreparedStatementCreator, org.springframework.jdbc.core.PreparedStatementSetter)` + +```java + protected int update(final PreparedStatementCreator psc, @Nullable final PreparedStatementSetter pss) + throws DataAccessException { + + logger.debug("Executing prepared SQL update"); + + return updateCount(execute(psc, ps -> { + try { + if (pss != null) { + // 设置请求参数 + pss.setValues(ps); + } + int rows = ps.executeUpdate(); + if (logger.isTraceEnabled()) { + logger.trace("SQL update affected " + rows + " rows"); + } + return rows; + } + finally { + if (pss instanceof ParameterDisposer) { + ((ParameterDisposer) pss).cleanupParameters(); + } + } + })); + } + +``` + + + + + diff --git a/docs/Spring/Spring5新特性/Spring-spring-components.md b/docs/Spring/Spring5新特性/Spring-spring-components.md new file mode 100644 index 0000000..10bef93 --- /dev/null +++ b/docs/Spring/Spring5新特性/Spring-spring-components.md @@ -0,0 +1,124 @@ +# Spring5 新特性 - spring.components +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) + + +## 解析 +- 相关类: `org.springframework.context.index.CandidateComponentsIndexLoader` +- 测试用例: `org.springframework.context.annotation.ClassPathScanningCandidateComponentProviderTests.defaultsWithIndex`,`org.springframework.context.index.CandidateComponentsIndexLoaderTests` +- `CandidateComponentsIndexLoader`是怎么找出来的,全文搜索`spring.components` +### 使用介绍 +- 下面是从`resources/example/scannable/spring.components`测试用例中复制过来的,从中可以发现等号左侧放的是我们写的组件,等号右边是属于什么组件 +``` +example.scannable.AutowiredQualifierFooService=example.scannable.FooService +example.scannable.DefaultNamedComponent=org.springframework.stereotype.Component +example.scannable.NamedComponent=org.springframework.stereotype.Component +example.scannable.FooService=example.scannable.FooService +example.scannable.FooServiceImpl=org.springframework.stereotype.Component,example.scannable.FooService +example.scannable.ScopedProxyTestBean=example.scannable.FooService +example.scannable.StubFooDao=org.springframework.stereotype.Component +example.scannable.NamedStubDao=org.springframework.stereotype.Component +example.scannable.ServiceInvocationCounter=org.springframework.stereotype.Component +example.scannable.sub.BarComponent=org.springframework.stereotype.Component +``` + +### debug +- 入口 `org.springframework.context.index.CandidateComponentsIndexLoader.loadIndex` +```java + @Nullable + public static CandidateComponentsIndex loadIndex(@Nullable ClassLoader classLoader) { + ClassLoader classLoaderToUse = classLoader; + if (classLoaderToUse == null) { + classLoaderToUse = CandidateComponentsIndexLoader.class.getClassLoader(); + } + return cache.computeIfAbsent(classLoaderToUse, CandidateComponentsIndexLoader::doLoadIndex); + } + +``` +```java + /** + * 解析 META-INF/spring.components 文件 + * @param classLoader + * @return + */ + @Nullable + private static CandidateComponentsIndex doLoadIndex(ClassLoader classLoader) { + if (shouldIgnoreIndex) { + return null; + } + + try { + Enumeration urls = classLoader.getResources(COMPONENTS_RESOURCE_LOCATION); + if (!urls.hasMoreElements()) { + return null; + } + List result = new ArrayList<>(); + while (urls.hasMoreElements()) { + URL url = urls.nextElement(); + // 读取META-INF/spring.components文件转换成map对象 + Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url)); + result.add(properties); + } + if (logger.isDebugEnabled()) { + logger.debug("Loaded " + result.size() + "] index(es)"); + } + int totalCount = result.stream().mapToInt(Properties::size).sum(); + // 查看CandidateComponentsIndex方法 + return (totalCount > 0 ? new CandidateComponentsIndex(result) : null); + } + catch (IOException ex) { + throw new IllegalStateException("Unable to load indexes from location [" + + COMPONENTS_RESOURCE_LOCATION + "]", ex); + } + } + +``` + +```java + CandidateComponentsIndex(List content) { + this.index = parseIndex(content); + } + + /** + * 解析 MATE-INF\spring.components 转换成 map + * + * @param content + * @return + */ + private static MultiValueMap parseIndex(List content) { + MultiValueMap index = new LinkedMultiValueMap<>(); + for (Properties entry : content) { + entry.forEach((type, values) -> { + String[] stereotypes = ((String) values).split(","); + for (String stereotype : stereotypes) { + index.add(stereotype, new Entry((String) type)); + } + }); + } + return index; + } +``` + + + + + + +- 该类给`org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents`提供了帮助 + +```java + public Set findCandidateComponents(String basePackage) { + // 扫描 + /** + * if 测试用例: {@link org.springframework.context.annotation.ClassPathScanningCandidateComponentProviderTests#defaultsWithIndex()} + * 解析 spring.components文件 + */ + if (this.componentsIndex != null && indexSupportsIncludeFilters()) { + return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); + } + else { + return scanCandidateComponents(basePackage); + } + } + +``` \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-AnnotationUtils.md b/docs/Spring/clazz/Spring-AnnotationUtils.md new file mode 100644 index 0000000..0da8161 --- /dev/null +++ b/docs/Spring/clazz/Spring-AnnotationUtils.md @@ -0,0 +1,518 @@ +# Spring AnnotationUtils +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) +- `org.springframework.core.annotation.AnnotationUtils`提供了注解相关的方法 + 1. getAnnotation: 获取注解 + 1. findAnnotation: 寻找注解 + 1. getValue: 获取属性值 + 1. getDefaultValue: 获取默认值 + + +## getAnnotation +- 测试用例如下 +```java + @Test + public void findMethodAnnotationOnLeaf() throws Exception { + Method m = Leaf.class.getMethod("annotatedOnLeaf"); + assertNotNull(m.getAnnotation(Order.class)); + assertNotNull(getAnnotation(m, Order.class)); + assertNotNull(findAnnotation(m, Order.class)); + } + +``` +- `org.springframework.core.annotation.AnnotationUtils.getAnnotation(java.lang.reflect.Method, java.lang.Class)` +```java + /** + * Get a single {@link Annotation} of {@code annotationType} from the + * supplied {@link Method}, where the annotation is either present + * or meta-present on the method. + * Correctly handles bridge {@link Method Methods} generated by the compiler. + * Note that this method supports only a single level of meta-annotations. + * For support for arbitrary levels of meta-annotations, use + * {@link #findAnnotation(Method, Class)} instead. + * + * @param method the method to look for annotations on + * 被检查的函数 + * @param annotationType the annotation type to look for + * 需要检测的注解类型 + * @return the first matching annotation, or {@code null} if not found + * @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method) + * @see #getAnnotation(AnnotatedElement, Class) + */ + @Nullable + public static A getAnnotation(Method method, Class annotationType) { + // 函数 + Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method); + // 强制转换 + return getAnnotation((AnnotatedElement) resolvedMethod, annotationType); + } + +``` +- method + +  + +- annotationType + +  + +```java + @Nullable + public static A getAnnotation(AnnotatedElement annotatedElement, Class annotationType) { + try { + // 获取注解 + A annotation = annotatedElement.getAnnotation(annotationType); + if (annotation == null) { + for (Annotation metaAnn : annotatedElement.getAnnotations()) { + annotation = metaAnn.annotationType().getAnnotation(annotationType); + if (annotation != null) { + break; + } + } + } + return (annotation != null ? synthesizeAnnotation(annotation, annotatedElement) : null); + } catch (Throwable ex) { + handleIntrospectionFailure(annotatedElement, ex); + return null; + } + } + +``` +- `org.springframework.core.annotation.AnnotationUtils.synthesizeAnnotation(A, java.lang.reflect.AnnotatedElement)` +```java + public static A synthesizeAnnotation( + A annotation, @Nullable AnnotatedElement annotatedElement) { + + return synthesizeAnnotation(annotation, (Object) annotatedElement); + } + +``` +```java + /** + * 注解是否存在别名,没有直接返回 + * + * @param annotation 注解 + * @param annotatedElement 函数 + * @param + * @return + */ + @SuppressWarnings("unchecked") + static A synthesizeAnnotation(A annotation, @Nullable Object annotatedElement) { + if (annotation instanceof SynthesizedAnnotation || hasPlainJavaAnnotationsOnly(annotatedElement)) { + return annotation; + } + // 具体的注解 + Class extends Annotation> annotationType = annotation.annotationType(); + if (!isSynthesizable(annotationType)) { + return annotation; + } + + DefaultAnnotationAttributeExtractor attributeExtractor = + new DefaultAnnotationAttributeExtractor(annotation, annotatedElement); + InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor); + + // Can always expose Spring's SynthesizedAnnotation marker since we explicitly check for a + // synthesizable annotation before (which needs to declare @AliasFor from the same package) + Class>[] exposedInterfaces = new Class>[]{annotationType, SynthesizedAnnotation.class}; + return (A) Proxy.newProxyInstance(annotation.getClass().getClassLoader(), exposedInterfaces, handler); + } + +``` +-`org.springframework.core.annotation.AnnotationUtils.isSynthesizable` +```java + @SuppressWarnings("unchecked") + private static boolean isSynthesizable(Class extends Annotation> annotationType) { + if (hasPlainJavaAnnotationsOnly(annotationType)) { + return false; + } + // 从缓存中获取当前注解,不存在null + Boolean synthesizable = synthesizableCache.get(annotationType); + if (synthesizable != null) { + return synthesizable; + } + + synthesizable = Boolean.FALSE; + for (Method attribute : getAttributeMethods(annotationType)) { + if (!getAttributeAliasNames(attribute).isEmpty()) { + synthesizable = Boolean.TRUE; + break; + } + // 获取返回值类型 + Class> returnType = attribute.getReturnType(); + + // 根据返回值做不同处理 + if (Annotation[].class.isAssignableFrom(returnType)) { + Class extends Annotation> nestedAnnotationType = + (Class extends Annotation>) returnType.getComponentType(); + if (isSynthesizable(nestedAnnotationType)) { + synthesizable = Boolean.TRUE; + break; + } + } else if (Annotation.class.isAssignableFrom(returnType)) { + Class extends Annotation> nestedAnnotationType = (Class extends Annotation>) returnType; + if (isSynthesizable(nestedAnnotationType)) { + synthesizable = Boolean.TRUE; + break; + } + } + } + + synthesizableCache.put(annotationType, synthesizable); + return synthesizable; + } + +``` + +- `org.springframework.core.annotation.AnnotationUtils#getAttributeMethods` + +```java + static List getAttributeMethods(Class extends Annotation> annotationType) { + List methods = attributeMethodsCache.get(annotationType); + if (methods != null) { + return methods; + } + + methods = new ArrayList<>(); + // annotationType.getDeclaredMethods() 获取注解中的方法 + for (Method method : annotationType.getDeclaredMethods()) { + if (isAttributeMethod(method)) { + ReflectionUtils.makeAccessible(method); + methods.add(method); + } + } + + // 缓存 key:注解,value:函数列表 + attributeMethodsCache.put(annotationType, methods); + // 函数列表 + return methods; + } + +``` + +- `org.springframework.core.annotation.AnnotationUtils#isAttributeMethod` + +```java + /** + * Determine if the supplied {@code method} is an annotation attribute method. + * + * 做3个判断 + * + * 函数不为空(method != null) + * 参数列表是不是空(method.getParameterCount() == 0) + * 返回类型不是void(method.getReturnType() != void.class) + * + * + * @param method the method to check + * @return {@code true} if the method is an attribute method + * @since 4.2 + */ + static boolean isAttributeMethod(@Nullable Method method) { + return (method != null && method.getParameterCount() == 0 && method.getReturnType() != void.class); + } + +``` + +- `org.springframework.util.ReflectionUtils#makeAccessible(java.lang.reflect.Method)` + +```java +@SuppressWarnings("deprecation") // on JDK 9 + public static void makeAccessible(Method method) { + // 1. 方法修饰符是不是public + // 2. 注解是不是public + // 3. 是否重写 + if ((!Modifier.isPublic(method.getModifiers()) || + !Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible()) { + method.setAccessible(true); + } + } +``` + +处理结果 + + + + + +处理结果和Order定义相同 + +```java +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) +@Documented +public @interface Order { + + /** + * The order value. + * Default is {@link Ordered#LOWEST_PRECEDENCE}. + * + * 启动顺序,默认integer最大值 + * @see Ordered#getOrder() + */ + int value() default Ordered.LOWEST_PRECEDENCE; + +} +``` + + + +最终返回 + + + + + + + + + + + +## findAnnotation + +- `org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.Method, java.lang.Class)` + + ```java + @SuppressWarnings("unchecked") + @Nullable + public static A findAnnotation(Method method, @Nullable Class annotationType) { + Assert.notNull(method, "Method must not be null"); + if (annotationType == null) { + return null; + } + // 创建注解缓存,key:被扫描的函数,value:注解 + AnnotationCacheKey cacheKey = new AnnotationCacheKey(method, annotationType); + // 从findAnnotationCache获取缓存 + A result = (A) findAnnotationCache.get(cacheKey); + + if (result == null) { + Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method); + // 寻找注解 + result = findAnnotation((AnnotatedElement) resolvedMethod, annotationType); + if (result == null) { + result = searchOnInterfaces(method, annotationType, method.getDeclaringClass().getInterfaces()); + } + + Class> clazz = method.getDeclaringClass(); + while (result == null) { + clazz = clazz.getSuperclass(); + if (clazz == null || clazz == Object.class) { + break; + } + Set annotatedMethods = getAnnotatedMethodsInBaseType(clazz); + if (!annotatedMethods.isEmpty()) { + for (Method annotatedMethod : annotatedMethods) { + if (isOverride(method, annotatedMethod)) { + Method resolvedSuperMethod = BridgeMethodResolver.findBridgedMethod(annotatedMethod); + result = findAnnotation((AnnotatedElement) resolvedSuperMethod, annotationType); + if (result != null) { + break; + } + } + } + } + if (result == null) { + result = searchOnInterfaces(method, annotationType, clazz.getInterfaces()); + } + } + + if (result != null) { + // 处理注解 + result = synthesizeAnnotation(result, method); + // 添加缓存 + findAnnotationCache.put(cacheKey, result); + } + } + // 返回 + return result; + } + + ``` + + + +- `org.springframework.core.annotation.AnnotationUtils.AnnotationCacheKey` + + ```java + private static final class AnnotationCacheKey implements Comparable { + + /** + * 带有注解的函数或者类 + */ + private final AnnotatedElement element; + + /** + * 注解 + */ + private final Class extends Annotation> annotationType; + + public AnnotationCacheKey(AnnotatedElement element, Class extends Annotation> annotationType) { + this.element = element; + this.annotationType = annotationType; + } + + } + ``` + + + +- `org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.AnnotatedElement, java.lang.Class)` + + ```java + @Nullable + public static A findAnnotation( + AnnotatedElement annotatedElement, @Nullable Class annotationType) { + // 注解类型不为空 + if (annotationType == null) { + return null; + } + + // Do NOT store result in the findAnnotationCache since doing so could break + // findAnnotation(Class, Class) and findAnnotation(Method, Class). + // 寻找注解 + A ann = findAnnotation(annotatedElement, annotationType, new HashSet<>()); + return (ann != null ? synthesizeAnnotation(ann, annotatedElement) : null); + } + + ``` + + + + + +- `org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.AnnotatedElement, java.lang.Class, java.util.Set)` + + ```java + @Nullable + private static A findAnnotation( + AnnotatedElement annotatedElement, Class annotationType, Set visited) { + try { + // 直接获取注解 + A annotation = annotatedElement.getDeclaredAnnotation(annotationType); + if (annotation != null) { + return annotation; + } + // 多级注解 + for (Annotation declaredAnn : getDeclaredAnnotations(annotatedElement)) { + Class extends Annotation> declaredType = declaredAnn.annotationType(); + // 注解是否 由java.lang.annotation提供 + if (!isInJavaLangAnnotationPackage(declaredType) && visited.add(declaredAnn)) { + annotation = findAnnotation((AnnotatedElement) declaredType, annotationType, visited); + if (annotation != null) { + return annotation; + } + } + } + } catch (Throwable ex) { + handleIntrospectionFailure(annotatedElement, ex); + } + return null; + } + + ``` + + + + + +- `synthesizeAnnotation`方法就不再重复一遍了可以看上文 + + + + + + + +## getValue + +- 测试用例 + + ```java + @Test + public void getValueFromAnnotation() throws Exception { + Method method = SimpleFoo.class.getMethod("something", Object.class); + Order order = findAnnotation(method, Order.class); + + assertEquals(1, getValue(order, VALUE)); + assertEquals(1, getValue(order)); + } + ``` + + + +- `org.springframework.core.annotation.AnnotationUtils#getValue(java.lang.annotation.Annotation, java.lang.String)` + +```java + @Nullable + public static Object getValue(@Nullable Annotation annotation, @Nullable String attributeName) { + if (annotation == null || !StringUtils.hasText(attributeName)) { + return null; + } + try { + // 根据attributeName获取注解对应函数 + Method method = annotation.annotationType().getDeclaredMethod(attributeName); + ReflectionUtils.makeAccessible(method); + // 反射执行方法 + return method.invoke(annotation); + } catch (NoSuchMethodException ex) { + return null; + } catch (InvocationTargetException ex) { + rethrowAnnotationConfigurationException(ex.getTargetException()); + throw new IllegalStateException("Could not obtain value for annotation attribute '" + + attributeName + "' in " + annotation, ex); + } catch (Throwable ex) { + handleIntrospectionFailure(annotation.getClass(), ex); + return null; + } + } + +``` + + + +```java + @Nullable + public static Object getValue(Annotation annotation) { + return getValue(annotation, VALUE); + } + +``` + + + + + + + +## getDefaultValue + +- `org.springframework.core.annotation.AnnotationUtils#getDefaultValue(java.lang.annotation.Annotation)` + + + +```java + @Nullable + public static Object getDefaultValue(Annotation annotation) { + return getDefaultValue(annotation, VALUE); + } + +``` + +```java + @Nullable + public static Object getDefaultValue( + @Nullable Class extends Annotation> annotationType, @Nullable String attributeName) { + + if (annotationType == null || !StringUtils.hasText(attributeName)) { + return null; + } + try { + // 直接获取defaultValue + return annotationType.getDeclaredMethod(attributeName).getDefaultValue(); + } catch (Throwable ex) { + handleIntrospectionFailure(annotationType, ex); + return null; + } + } + +``` + diff --git a/docs/Spring/clazz/Spring-BeanFactoryPostProcessor.md b/docs/Spring/clazz/Spring-BeanFactoryPostProcessor.md new file mode 100644 index 0000000..81fe47a --- /dev/null +++ b/docs/Spring/clazz/Spring-BeanFactoryPostProcessor.md @@ -0,0 +1,447 @@ +# Spring BeanFactoryPostProcessor +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) +- 作用: 定制或修改`BeanDefinition`的属性 + + +## Demo +```java +public class ChangeAttrBeanPostProcessor implements BeanFactoryPostProcessor { + private Set attr; + + public ChangeAttrBeanPostProcessor() { + attr = new HashSet<>(); + } + + public Set getAttr() { + return attr; + } + + public void setAttr(Set attr) { + this.attr = attr; + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames(); + for (String beanName : beanDefinitionNames) { + BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); + + StringValueResolver stringValueResolver = new StringValueResolver() { + @Override + public String resolveStringValue(String strVal) { + if (attr.contains(strVal)) { + return "隐藏属性"; + } + else { + return strVal; + } + } + }; + BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(stringValueResolver); + visitor.visitBeanDefinition(beanDefinition); + } + } +} +``` + +```java +public class BeanFactoryPostProcessorSourceCode { + public static void main(String[] args) { + ApplicationContext context = new ClassPathXmlApplicationContext("BeanFactoryPostProcessor-demo.xml"); + Apple apple = context.getBean("apple", Apple.class); + System.out.println(apple); + } +} +``` + +```xml + + + + + + hc + + + + + + + + +``` + + + +## 初始化 + +- `org.springframework.context.support.AbstractApplicationContext#refresh` + + ```JAVA + invokeBeanFactoryPostProcessors(beanFactory); + ``` + + ```JAVA + 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())); + } + } + + ``` + +- `org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List)` + + ```JAVA + public static void invokeBeanFactoryPostProcessors( + ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) { + + // Invoke BeanDefinitionRegistryPostProcessors first, if any. + Set processedBeans = new HashSet<>(); + // 判断是否为BeanDefinitionRegistry类 + if (beanFactory instanceof BeanDefinitionRegistry) { + BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; + // 存放 BeanFactoryPostProcessor + List regularPostProcessors = new ArrayList<>(); + // 存放 BeanDefinitionRegistryPostProcessor + List registryProcessors = new ArrayList<>(); + + // 2.首先处理入参中的beanFactoryPostProcessors + for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { + // 判断是否是BeanDefinitionRegistryPostProcessor + if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { + BeanDefinitionRegistryPostProcessor registryProcessor = + (BeanDefinitionRegistryPostProcessor) postProcessor; + // + registryProcessor.postProcessBeanDefinitionRegistry(registry); + // BeanDefinitionRegistryPostProcessor 添加 + // 执行 postProcessBeanFactory + registryProcessors.add(registryProcessor); + } + // 这部分else 内容就是 BeanFactoryPostProcessor + else { + // BeanFactoryPostProcessor 添加 + 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 currentRegistryProcessors = new ArrayList<>(); + + // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. + /** + * 调用实现{@link PriorityOrdered}\{@link BeanDefinitionRegistryPostProcessor} + * todo: 2020年1月16日 解析方法 + * {@link DefaultListableBeanFactory#getBeanNamesForType(java.lang.Class, boolean, boolean)} + */ + 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); + } + } + // 排序Order + 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! + // 配置文件中的 BeanFactoryPostProcessor 处理 + String[] postProcessorNames = + beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); + + // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, + // Ordered, and the rest. + List priorityOrderedPostProcessors = new ArrayList<>(); + List orderedPostProcessorNames = new ArrayList<>(); + List 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 orderedPostProcessors = new ArrayList<>(); + for (String postProcessorName : orderedPostProcessorNames) { + orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); + } + sortPostProcessors(orderedPostProcessors, beanFactory); + invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); + + // Finally, invoke all other BeanFactoryPostProcessors. + // 配置文件中自定义的 BeanFactoryPostProcessor 注册 + List nonOrderedPostProcessors = new ArrayList<>(); + 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(); + } + ``` + + + + + + + + + + + +## InstantiationAwareBeanPostProcessor + +```java + protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { + PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this); + } +``` + + + +```java + public static void registerBeanPostProcessors( + ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { + // 获取 BeanPostProcessor + 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. + // BeanPostProcessor 通过PriorityOrdered保证顺序 + List priorityOrderedPostProcessors = new ArrayList<>(); + // MergedBeanDefinitionPostProcessor + List internalPostProcessors = new ArrayList<>(); + // 有序的 BeanPostProcessor + List orderedPostProcessorNames = new ArrayList<>(); + // 无序的 BeanPostProcessor + List nonOrderedPostProcessorNames = new ArrayList<>(); + for (String ppName : postProcessorNames) { + if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { + BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); + priorityOrderedPostProcessors.add(pp); + // 类型判断放入相应的list + 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. + /** + * 有{@link org.springframework.core.annotation.Order} 相关操作 + */ + sortPostProcessors(priorityOrderedPostProcessors, beanFactory); + // 注册 BeanPostProcessor 和 PriorityOrdered 实现 + registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); + + // Next, register the BeanPostProcessors that implement Ordered. + List orderedPostProcessors = new ArrayList<>(); + for (String ppName : orderedPostProcessorNames) { + BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); + orderedPostProcessors.add(pp); + if (pp instanceof MergedBeanDefinitionPostProcessor) { + internalPostProcessors.add(pp); + } + } + sortPostProcessors(orderedPostProcessors, beanFactory); + // 注册 实现Order 和 BeanPostProcessor + registerBeanPostProcessors(beanFactory, orderedPostProcessors); + + // Now, register all regular BeanPostProcessors. + List nonOrderedPostProcessors = new ArrayList<>(); + for (String ppName : nonOrderedPostProcessorNames) { + BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); + nonOrderedPostProcessors.add(pp); + if (pp instanceof MergedBeanDefinitionPostProcessor) { + internalPostProcessors.add(pp); + } + } + // 注册无序的 BeanPostProcessor + registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); + + // Finally, re-register all internal BeanPostProcessors. + sortPostProcessors(internalPostProcessors, beanFactory); + // 注册 MergedBeanDefinitionPostProcessor + 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). + // 添加 ApplicationListenerDetector + beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); + } + + +``` + + + +- 测试用Bean + +```java +public class DemoInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { + @Override + public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException { + System.out.println("init bean beanClass = " + beanClass.getSimpleName() + " beanName = " + beanName); + return null; + } +} +``` + + + +- 按照笔者的注释,可以知道`DemoInstantiationAwareBeanPostProcessor` 这个类是一个无序Bean + +  + + + + + +- 注册方法信息截图 + + + + + + + +### 使用阶段(调用阶段) + +在`org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])`中有如下代码 + +```JAVA + Object bean = resolveBeforeInstantiation(beanName, mbdToUse); +``` + +- `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation` + +```JAVA +@Nullable + protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { + Object bean = null; + if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { + // Make sure bean class is actually resolved at this point. + if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { + Class> targetType = determineTargetType(beanName, mbd); + if (targetType != null) { + /** + * 主要实现{@link org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(java.lang.Class, java.lang.String)} + */ + bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); + if (bean != null) { + bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); + } + } + } + mbd.beforeInstantiationResolved = (bean != null); + } + return bean; + } +``` + +- `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation` + +```JAVA + @Nullable + protected Object applyBeanPostProcessorsBeforeInstantiation(Class> beanClass, String beanName) { + for (BeanPostProcessor bp : getBeanPostProcessors()) { + if (bp instanceof InstantiationAwareBeanPostProcessor) { + InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; + // 调用自定义实现 + Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); + if (result != null) { + return result; + } + } + } + return null; + } + +``` + +这个地方已经可以看到`InstantiationAwareBeanPostProcessor`出现了,并且调用了方法`postProcessBeforeInstantiation`,此处就可以调用我们的自定义方法了 + + \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-DefaultSingletonBeanRegistry.md b/docs/Spring/clazz/Spring-DefaultSingletonBeanRegistry.md new file mode 100644 index 0000000..ccd1231 --- /dev/null +++ b/docs/Spring/clazz/Spring-DefaultSingletonBeanRegistry.md @@ -0,0 +1,278 @@ +# DefaultSingletonBeanRegistry +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) +- 源码路径: `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry` +- 官方提供的测试类: `org.springframework.beans.factory.support.DefaultSingletonBeanRegistryTests` + +类图 + +## 注册方法解析 +- 从名字可以看出这是一个单例对象的注册类 +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.registerSingleton` + + + +- 测试用例出发 + + ```java + @Test + public void testSingletons() { + DefaultSingletonBeanRegistry beanRegistry = new DefaultSingletonBeanRegistry(); + + TestBean tb = new TestBean(); + beanRegistry.registerSingleton("tb", tb); + assertSame(tb, beanRegistry.getSingleton("tb")); + + TestBean tb2 = (TestBean) beanRegistry.getSingleton("tb2", new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return new TestBean(); + } + }); + assertSame(tb2, beanRegistry.getSingleton("tb2")); + + assertSame(tb, beanRegistry.getSingleton("tb")); + assertSame(tb2, beanRegistry.getSingleton("tb2")); + assertEquals(2, beanRegistry.getSingletonCount()); + String[] names = beanRegistry.getSingletonNames(); + assertEquals(2, names.length); + assertEquals("tb", names[0]); + assertEquals("tb2", names[1]); + + beanRegistry.destroySingletons(); + assertEquals(0, beanRegistry.getSingletonCount()); + assertEquals(0, beanRegistry.getSingletonNames().length); + } + + ``` + + + +- 第一个关注的方法`org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#registerSingleton` 注册单例对象 + +```java + /** + * 注册一个单例对象 + * + * @param beanName the name of the bean + * @param singletonObject the existing singleton object + * @throws IllegalStateException + */ + @Override + public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { + Assert.notNull(beanName, "Bean name must not be null"); + Assert.notNull(singletonObject, "Singleton object must not be null"); + synchronized (this.singletonObjects) { + // 通过beanName获取单例对象 + Object oldObject = this.singletonObjects.get(beanName); + // 不为空异常 + if (oldObject != null) { + throw new IllegalStateException("Could not register object [" + singletonObject + + "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound"); + } + // 添加方法 + addSingleton(beanName, singletonObject); + } + } + +``` +```java + /** + * Add the given singleton object to the singleton cache of this factory. + * To be called for eager registration of singletons. + * + * 添加单例对象的操作方法 + * + * @param beanName the name of the bean + * @param singletonObject the singleton object + */ + protected void addSingleton(String beanName, Object singletonObject) { + synchronized (this.singletonObjects) { + this.singletonObjects.put(beanName, singletonObject); + this.singletonFactories.remove(beanName); + this.earlySingletonObjects.remove(beanName); + this.registeredSingletons.add(beanName); + } + } +``` +- 这些变量是什么 +```java + /** + * 单例对象的缓存: beanName -> Object + */ + private final Map singletonObjects = new ConcurrentHashMap<>(256); + + /** + * 单例工厂的缓存: beanName -> ObjectFactory。 + */ + private final Map> singletonFactories = new HashMap<>(16); + + /** + * 延迟加载的单例对象缓存: beanName -> Object + */ + private final Map earlySingletonObjects = new HashMap<>(16); + + /** + * 已经注册过的单例对象名称(beanName) + */ + private final Set registeredSingletons = new LinkedHashSet<>(256); + + /** + * 当前正在创建的单例对象名称(beanName) + */ + private final Set singletonsCurrentlyInCreation = + Collections.newSetFromMap(new ConcurrentHashMap<>(16)); + + private final Set inCreationCheckExclusions = + Collections.newSetFromMap(new ConcurrentHashMap<>(16)); + /** + * 摧毁单例对象 + */ + private final Map disposableBeans = new LinkedHashMap<>(); + private final Map> containedBeanMap = new ConcurrentHashMap<>(16); + /** + * bean 和beanName的关系 + */ + private final Map> dependentBeanMap = new ConcurrentHashMap<>(64); + /** + * bean 依赖关系 beanName -> 依赖关系 + */ + private final Map> dependenciesForBeanMap = new ConcurrentHashMap<>(64); + /** + * 异常列表 + */ + @Nullable + private Set suppressedExceptions; + /** + * 标记是否在 destroySingletons 上 + */ + private boolean singletonsCurrentlyInDestruction = false; + +``` + +- 注册方法至此结束 + +## 获取方法解析 +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(java.lang.String)` +```java + @Override + @Nullable + public Object getSingleton(String beanName) { + return getSingleton(beanName, true); + } +``` + +```java + @Nullable + protected Object getSingleton(String beanName, boolean allowEarlyReference) { + // 从列表中获取单例对象 + Object singletonObject = this.singletonObjects.get(beanName); + // 判断当前beanName是否存在 + if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { + synchronized (this.singletonObjects) { + // 从延迟加载中获取 + singletonObject = this.earlySingletonObjects.get(beanName); + if (singletonObject == null && allowEarlyReference) { + // 从singletonFactories获取ObjectFactory + ObjectFactory> singletonFactory = this.singletonFactories.get(beanName); + if (singletonFactory != null) { + // 获取对象 + singletonObject = singletonFactory.getObject(); + // 加入缓存 + this.earlySingletonObjects.put(beanName, singletonObject); + this.singletonFactories.remove(beanName); + } + } + } + } + return singletonObject; + } + +``` + +- 获取单例对象的本质就是从map中获取 ObjectFactory 进而执行 getObject() +`ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);` +- 测试方法 +```java + + TestBean tb2 = (TestBean) beanRegistry.getSingleton("tb2", new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return new TestBean(); + } + }); +``` + +- 获取单例对象的方式 + +```java +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; + } + } +``` + +不难发现最后都是通过`singletonObject = singletonFactory.getObject();`进行获取 + +这个地方的方法实际上就是测试类中的 + +```java +new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return new TestBean(); + } + } +``` + +通过`getObject`就可以获取当前对象 \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-OrderComparator.md b/docs/Spring/clazz/Spring-OrderComparator.md new file mode 100644 index 0000000..173f546 --- /dev/null +++ b/docs/Spring/clazz/Spring-OrderComparator.md @@ -0,0 +1,98 @@ +# Spring OrderComparator +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) + + +```java + private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) { + boolean p1 = (o1 instanceof PriorityOrdered); + boolean p2 = (o2 instanceof PriorityOrdered); + if (p1 && !p2) { + return -1; + } else if (p2 && !p1) { + return 1; + } + + int i1 = getOrder(o1, sourceProvider); + int i2 = getOrder(o2, sourceProvider); + // 对比两个Order值得大小返回 + return Integer.compare(i1, i2); + } + +``` + +```java + private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) { + Integer order = null; + if (obj != null && sourceProvider != null) { + // 获取Order + Object orderSource = sourceProvider.getOrderSource(obj); + if (orderSource != null) { + if (orderSource.getClass().isArray()) { + // 获取 OrderSourceProvider 的值 + Object[] sources = ObjectUtils.toObjectArray(orderSource); + for (Object source : sources) { + // 找 order 返回 + order = findOrder(source); + if (order != null) { + break; + } + } + } else { + // 寻找 order + order = findOrder(orderSource); + } + } + } + return (order != null ? order : getOrder(obj)); + } + +``` + +- 测试用例 +```java + @Test + public void compareWithSourceProviderArray() { + Comparator customComparator = this.comparator.withSourceProvider( + new TestSourceProvider(5L, new Object[]{new StubOrdered(10), new StubOrdered(-25)})); + assertEquals(-1, customComparator.compare(5L, new Object())); + } + +``` + + + + + +```java + @Nullable + protected Integer findOrder(Object obj) { + // 获取Ordered实现类 + return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null); + } + +``` + +```java + private static final class StubOrdered implements Ordered { + + private final int order; + + + public StubOrdered(int order) { + this.order = order; + } + + @Override + public int getOrder() { + return this.order; + } + } + +``` + + + + + +最终`Integer.compare(i1, i2)`比较返回 OK ! \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-scan.md b/docs/Spring/clazz/Spring-scan.md new file mode 100644 index 0000000..5e03fe9 --- /dev/null +++ b/docs/Spring/clazz/Spring-scan.md @@ -0,0 +1,534 @@ +# Spring scan +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) + +## 解析 +- Spring 注解形式使用有下面两种方式 + 1. 通过`AnnotationConfigApplicationContext`参数:扫描包 + 2. 通过xml配置`context:component-scan`属性`base-package` +```java + AnnotationConfigApplicationContext aac = + new AnnotationConfigApplicationContext("com.huifer.source.spring.ann"); +``` +```xml + + +``` + +- 目标明确开始找入口方法 +- `AnnotationConfigApplicationContext`直接点进去看就找到了 +```java +public AnnotationConfigApplicationContext(String... basePackages) { + this(); + // 扫描包 + scan(basePackages); + refresh(); + } +``` +- `context:component-scan`寻找方式:冒号`:`钱+NamespaceHandler 或者全文搜索`component-scan`,最终找到`org.springframework.context.config.ContextNamespaceHandler` +```java +public class ContextNamespaceHandler extends NamespaceHandlerSupport { + + @Override + public void init() { + registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); + registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); + registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); + registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); + registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser()); + registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); + registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser()); + registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser()); + } + +} +``` + +### org.springframework.context.annotation.ComponentScanBeanDefinitionParser + + + +- 实现`BeanDefinitionParser`直接看`parse`方法 +```java + @Override + @Nullable + public BeanDefinition parse(Element element, ParserContext parserContext) { + // 获取 base-package 属性值 + String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); + // 处理 ${} + basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); + // 分隔符`,;\t\n`切分 + String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, + ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); + + // Actually scan for bean definitions and register them. + // 扫描对象创建 + ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); + // 执行扫描方法 + Set beanDefinitions = scanner.doScan(basePackages); + // 注册组件,触发监听 + registerComponents(parserContext.getReaderContext(), beanDefinitions, element); + + return null; + } + +``` + +- 回过头看`AnnotationConfigApplicationContext` +### org.springframework.context.annotation.AnnotationConfigApplicationContext +```java +public AnnotationConfigApplicationContext(String... basePackages) { + this(); + // 扫描包 + scan(basePackages); + refresh(); + } +``` +```java + private final ClassPathBeanDefinitionScanner scanner; + + @Override + public void scan(String... basePackages) { + Assert.notEmpty(basePackages, "At least one base package must be specified"); + this.scanner.scan(basePackages); + } + +``` +- `org.springframework.context.annotation.ClassPathBeanDefinitionScanner.scan` +```java +public int scan(String... basePackages) { + + // 获取bean数量 + 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); + } +``` + +- 这个地方`doScan`似曾相识,他就是`org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse`中的`doScan`,下一步解析doScan + +### org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan + + + +```java + protected Set doScan(String... basePackages) { + Assert.notEmpty(basePackages, "At least one base package must be specified"); + Set beanDefinitions = new LinkedHashSet<>(); + for (String basePackage : basePackages) { + // 寻找组件 + Set candidates = findCandidateComponents(basePackage); + for (BeanDefinition candidate : candidates) { + // bean 作用域设置 + ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); + // 设置生命周期 + candidate.setScope(scopeMetadata.getScopeName()); + // 创建beanName + String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); + if (candidate instanceof AbstractBeanDefinition) { + // 设置默认属性 具体方法:org.springframework.beans.factory.support.AbstractBeanDefinition.applyDefaults + postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); + } + if (candidate instanceof AnnotatedBeanDefinition) { + // 读取Lazy,Primary 等注解 + AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); + } + // bean的重复检查 + if (checkCandidate(beanName, candidate)) { + // 创建 BeanDefinitionHolder + BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); + // 代理对象的处理 + definitionHolder = + AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); + // 放入list中,最后返回用 + beanDefinitions.add(definitionHolder); + // 注册bean + registerBeanDefinition(definitionHolder, this.registry); + } + } + } + return beanDefinitions; + } + +``` + + + +#### org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents + +```java + public Set findCandidateComponents(String basePackage) { + // 扫描 + if (this.componentsIndex != null && indexSupportsIncludeFilters()) { + return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); + } + else { + return scanCandidateComponents(basePackage); + } + } + +``` + + + +```java + /** + * 扫描当前包路径下的资源 + * @param basePackage + * @return + */ + private Set scanCandidateComponents(String basePackage) { + Set candidates = new LinkedHashSet<>(); + try { + // 字符串拼接出一个编译后的路径 classpath:// + // 这里替换了通配符 + String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + + resolveBasePackage(basePackage) + '/' + this.resourcePattern; + // 获取资源 + Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); + // 日志级别 + boolean traceEnabled = logger.isTraceEnabled(); + boolean debugEnabled = logger.isDebugEnabled(); + for (Resource resource : resources) { + if (traceEnabled) { + logger.trace("Scanning " + resource); + } + if (resource.isReadable()) { + try { + // 获取 MetadataReader + MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); + // 判断是否是 Component + if (isCandidateComponent(metadataReader)) { + ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); + sbd.setResource(resource); + sbd.setSource(resource); + if (isCandidateComponent(sbd)) { + if (debugEnabled) { + logger.debug("Identified candidate component class: " + resource); + } + candidates.add(sbd); + } + else { + if (debugEnabled) { + logger.debug("Ignored because not a concrete top-level class: " + resource); + } + } + } + else { + if (traceEnabled) { + logger.trace("Ignored because not matching any filter: " + resource); + } + } + } + catch (Throwable ex) { + throw new BeanDefinitionStoreException( + "Failed to read candidate component class: " + resource, ex); + } + } + else { + if (traceEnabled) { + logger.trace("Ignored because not readable: " + resource); + } + } + } + } + catch (IOException ex) { + throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); + } + return candidates; + } + +``` + + + +#### org.springframework.context.annotation.ScopeMetadataResolver#resolveScopeMetadata + + + +```java + /** + * 生命周期设置 + * + * @param definition the target bean definition + * @return + */ + @Override + public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) { + ScopeMetadata metadata = new ScopeMetadata(); + // 判断是否属于 AnnotatedBeanDefinition + if (definition instanceof AnnotatedBeanDefinition) { + AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition; + AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor( + annDef.getMetadata(), this.scopeAnnotationType); + if (attributes != null) { + // 获取 value 属性值并且设置 + metadata.setScopeName(attributes.getString("value")); + // 获取 proxyMode 属性值并且设置 + ScopedProxyMode proxyMode = attributes.getEnum("proxyMode"); + if (proxyMode == ScopedProxyMode.DEFAULT) { + proxyMode = this.defaultProxyMode; + } + metadata.setScopedProxyMode(proxyMode); + } + } + return metadata; + } + + +``` + +- `org.springframework.context.annotation.AnnotationScopeMetadataResolverTests#resolveScopeMetadataShouldReadScopedProxyModeFromAnnotation`测试用例 + +```java + @Test + public void resolveScopeMetadataShouldReadScopedProxyModeFromAnnotation() { + AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(AnnotatedWithScopedProxy.class); + ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(bd); + assertNotNull("resolveScopeMetadata(..) must *never* return null.", scopeMetadata); + assertEquals("request", scopeMetadata.getScopeName()); + assertEquals(TARGET_CLASS, scopeMetadata.getScopedProxyMode()); + } + +``` + + + +#### org.springframework.beans.factory.support.BeanNameGenerator#generateBeanName + +- 创建beanName `org.springframework.context.annotation.AnnotationBeanNameGenerator#generateBeanName` + + + +```java + @Override + public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { + if (definition instanceof AnnotatedBeanDefinition) { + // 如果存在bean(value="") value存在 + String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition); + if (StringUtils.hasText(beanName)) { + // Explicit bean name found. + return beanName; + } + } + // Fallback: generate a unique default bean name. + // 创建beanName + return buildDefaultBeanName(definition, registry); + } + +``` + +```java + @Nullable + protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) { + AnnotationMetadata amd = annotatedDef.getMetadata(); + Set types = amd.getAnnotationTypes(); + String beanName = null; + for (String type : types) { + AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type); + if (attributes != null && isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) { + // 获取注解的value 属性值 + Object value = attributes.get("value"); + if (value instanceof String) { + String strVal = (String) value; + // 判断是否存在值 + if (StringUtils.hasLength(strVal)) { + if (beanName != null && !strVal.equals(beanName)) { + throw new IllegalStateException("Stereotype annotations suggest inconsistent " + + "component names: '" + beanName + "' versus '" + strVal + "'"); + } + // beanName = value属性值 + beanName = strVal; + } + } + } + } + return beanName; + } + +``` + +```java +@Service(value = "dhc") +public class DemoService { + +} +``` + + + + + + + +- `org.springframework.context.annotation.AnnotationBeanNameGenerator#buildDefaultBeanName(org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.support.BeanDefinitionRegistry)` + - `org.springframework.context.annotation.AnnotationBeanNameGenerator#buildDefaultBeanName(org.springframework.beans.factory.config.BeanDefinition)` + + + +```JAVA + protected String buildDefaultBeanName(BeanDefinition definition) { + // 获取bean class name + String beanClassName = definition.getBeanClassName(); + Assert.state(beanClassName != null, "No bean class name set"); + // 获取短类名, + String shortClassName = ClassUtils.getShortName(beanClassName); + // 第一个字母小写 + return Introspector.decapitalize(shortClassName); + } + +``` + +```JAVA +@Configuration +public class BeanConfig { + @Scope(value =ConfigurableBeanFactory.SCOPE_PROTOTYPE) + @Bean(value = "hc") + public Ubean f() { + return new Ubean(); + } +} + +``` + + + + + + + +#### org.springframework.context.annotation.ClassPathBeanDefinitionScanner#postProcessBeanDefinition + +- 这个方法没什么难点,直接是set方法 + +```java + protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) { + beanDefinition.applyDefaults(this.beanDefinitionDefaults); + if (this.autowireCandidatePatterns != null) { + beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName)); + } + } + +``` + +```java + public void applyDefaults(BeanDefinitionDefaults defaults) { + setLazyInit(defaults.isLazyInit()); + setAutowireMode(defaults.getAutowireMode()); + setDependencyCheck(defaults.getDependencyCheck()); + setInitMethodName(defaults.getInitMethodName()); + setEnforceInitMethod(false); + setDestroyMethodName(defaults.getDestroyMethodName()); + setEnforceDestroyMethod(false); + } + +``` + +#### org.springframework.context.annotation.AnnotationConfigUtils#processCommonDefinitionAnnotations(org.springframework.beans.factory.annotation.AnnotatedBeanDefinition) + +```java + public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) { + processCommonDefinitionAnnotations(abd, abd.getMetadata()); + } + +``` + +```java +static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) { + // 获取 lazy 注解 + AnnotationAttributes lazy = attributesFor(metadata, Lazy.class); + if (lazy != null) { + abd.setLazyInit(lazy.getBoolean("value")); + } else if (abd.getMetadata() != metadata) { + lazy = attributesFor(abd.getMetadata(), Lazy.class); + if (lazy != null) { + abd.setLazyInit(lazy.getBoolean("value")); + } + } + + if (metadata.isAnnotated(Primary.class.getName())) { + abd.setPrimary(true); + } + AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class); + if (dependsOn != null) { + abd.setDependsOn(dependsOn.getStringArray("value")); + } + + AnnotationAttributes role = attributesFor(metadata, Role.class); + if (role != null) { + abd.setRole(role.getNumber("value").intValue()); + } + AnnotationAttributes description = attributesFor(metadata, Description.class); + if (description != null) { + abd.setDescription(description.getString("value")); + } + } +``` + + + +- 方法思路: + 1. 获取注解的属性值 + 2. 设置注解属性 + + + + + +#### org.springframework.context.annotation.ClassPathBeanDefinitionScanner#checkCandidate + +- 重复检查 + +```java + protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException { + // 判断当前 beanName 是否在注册表中 + if (!this.registry.containsBeanDefinition(beanName)) { + return true; + } + // 从注册表中获取 + BeanDefinition existingDef = this.registry.getBeanDefinition(beanName); + // 当前的bean + BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition(); + if (originatingDef != null) { + existingDef = originatingDef; + } + if (isCompatible(beanDefinition, existingDef)) { + return false; + } + throw new ConflictingBeanDefinitionException("Annotation-specified bean name '" + beanName + + "' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, " + + "non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]"); + } + +``` + + + + + +#### org.springframework.context.annotation.AnnotationConfigUtils#applyScopedProxyMode + + + +```JAVA + static BeanDefinitionHolder applyScopedProxyMode( + ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) { + + ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode(); + if (scopedProxyMode.equals(ScopedProxyMode.NO)) { + return definition; + } + boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS); + // 创建代理对象 + return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass); + } + +``` + diff --git a/docs/Spring/clazz/Spring-自定义标签解析.md b/docs/Spring/clazz/Spring-自定义标签解析.md new file mode 100644 index 0000000..8a700f8 --- /dev/null +++ b/docs/Spring/clazz/Spring-自定义标签解析.md @@ -0,0 +1,658 @@ +# Spring 自定义标签解析 +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) +- 与自定义标签解析相关的类 + 1. `org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser` + 2. `org.springframework.beans.factory.xml.NamespaceHandlerSupport` + +- 开始源码之前先搭建一个环境 + + +## 环境搭建 +- 创建对象 +```java +public class UserXtd { + private String userName; + private String emailAddress; + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getEmailAddress() { + return emailAddress; + } + + public void setEmailAddress(String emailAddress) { + this.emailAddress = emailAddress; + } +} +``` +- 创建 xsd 文件 +```xml + + + + + + + + + + + +``` +- 创建 namespaceHandler +```java +public class UserNamespaceHandler extends NamespaceHandlerSupport { + @Override + public void init() { + registerBeanDefinitionParser("myUser", new UserBeanDefinitionParser()); + } +} +``` +- 创建 beanDefinitionParser +```java +public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { + /** + * 标签对应class + * @param element the {@code Element} that is being parsed + * @return + */ + @Override + protected Class> getBeanClass(Element element) { + return UserXtd.class; + } + + + @Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + // 获取 userName 标签属性值 + String name = element.getAttribute("userName"); + // 获取 emailAddress 标签属性值 + String address = element.getAttribute("emailAddress"); + + if (StringUtils.hasText(name)) { + builder.addPropertyValue("userName", name); + } + if (StringUtils.hasText(address)) { + builder.addPropertyValue("emailAddress", address); + } + } +} + +``` +- 创建 resource/META-INF/spring.handlers +```text +http\://www.huifer.com/schema/user=com.huifer.source.spring.parser.UserNamespaceHandler +``` +- 创建 resource/META-INF/spring.schemas +```text +http\://www.huifer.com/schema/user.xsd=META-INF/spring-test.xsd +``` +- 创建测试用例xml +```xml + + + + + + +``` +- 创建 Java 运行方法 +```java +/** + * 自定义标签测试用例 + */ +public class XSDDemo { + public static void main(String[] args) { + ApplicationContext applicationContext = new ClassPathXmlApplicationContext("XTD-xml.xml"); + UserXtd user = (UserXtd) applicationContext.getBean("testUserBean"); + System.out.println(user.getEmailAddress()); + } +} +``` +- 这里我们希望输出结果是`huifer97@163.com`,运行后结果也确实是`huifer97@163.com` + +## 解析 DefaultNamespaceHandlerResolver +- 入口方法`org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions` +```java + 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 { + // 非spring 默认标签解析 + delegate.parseCustomElement(ele); + } + } + } + } + else { + delegate.parseCustomElement(root); + } + } + +``` +- 调用链路 +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(org.w3c.dom.Element)` + - `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)` + +```java + /** + * Parse a custom element (outside of the default namespace). + * + * 自定义标签解析 + * + * @param ele the element to parse + * @param containingBd the containing bean definition (if any) + * @return the resulting bean definition + */ + @Nullable + 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)); + } + +``` + + + +- `http://www.huifer.com/schema/user`和我们定义的xsd文件中的url相同,如何找到对应的NamespaceHandler,在`META-INF/spring.handlers`中有定义, + + `http\://www.huifer.com/schema/user=com.huifer.source.spring.parser.UserNamespaceHandler` + + `NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);`这行代码就是获取`spring.handlers`中的定义 + +- 处理方法`org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve` + + + +```java + /** + * Locate the {@link NamespaceHandler} for the supplied namespace URI + * from the configured mappings. + * + * 根据 namespaceUri 获取对应的 {@link NamespaceHandler} + * @param namespaceUri the relevant namespace URI + * @return the located {@link NamespaceHandler}, or {@code null} if none found + */ + @Override + @Nullable + public NamespaceHandler resolve(String namespaceUri) { + // 获取handlerMapping + Map handlerMappings = getHandlerMappings(); + // 从 handlerMapping 中获取类名 + 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); + // 调用init()方法,自定义类中实现 + namespaceHandler.init(); + // 放入缓存 + handlerMappings.put(namespaceUri, namespaceHandler); + // 返回自定义的 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); + } + } + } + +``` + + + +- `org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#getHandlerMappings`跟踪这个方法 + +```JAVA + /** + * Load the specified NamespaceHandler mappings lazily. + * + * 获取handlerMappings + */ + private Map getHandlerMappings() { + Map handlerMappings = this.handlerMappings; + } +``` + + + + + +- 这里直接存在数据了,他是从什么时候加载的? + +- `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions` + + 这个方法在注册bean定义的时候调用 + + ```java + public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { + BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); + int countBefore = getRegistry().getBeanDefinitionCount(); + // 注册方法 + // createReaderContext 初始化HandlerMapping + documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); + return getRegistry().getBeanDefinitionCount() - countBefore; + } + + ``` + +- 继续跟踪`createReaderContext` + + ```java + org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createReaderContext + ``` + + ```java + public XmlReaderContext createReaderContext(Resource resource) { + return new XmlReaderContext(resource, this.problemReporter, this.eventListener, + this.sourceExtractor, this, getNamespaceHandlerResolver()); + } + + ``` + +- 继续跟踪`getNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#getNamespaceHandlerResolver` + + ```java + public NamespaceHandlerResolver getNamespaceHandlerResolver() { + if (this.namespaceHandlerResolver == null) { + this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver(); + } + return this.namespaceHandlerResolver; + } + + ``` + +- 继续跟踪`createDefaultNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createDefaultNamespaceHandlerResolver` + + ```java + protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() { + ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader()); + return new DefaultNamespaceHandlerResolver(cl); + } + ``` + + + +- 继续跟踪`DefaultNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver` + + ```java + public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) { + this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); + } + + ``` + + 他回到了我们之前疑问的地方 `handlerMappings` 如何出现的 + + 断点 + +  + + ```JAVA + public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) { + this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); + } + ``` + + `public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";` + +  + + 此时还是空 + + 走完 + +  + + ```java + @Override + public String toString() { + return "NamespaceHandlerResolver using mappings " + getHandlerMappings(); + } + + ``` + + + +```JAVA + /** + * Load the specified NamespaceHandler mappings lazily. + * + * 获取handlerMappings + */ + private Map getHandlerMappings() { + Map handlerMappings = this.handlerMappings; + // 缓存不存在 + if (handlerMappings == null) { + synchronized (this) { + handlerMappings = this.handlerMappings; + if (handlerMappings == null) { + if (logger.isTraceEnabled()) { + logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]"); + } + try { + // 将本地文件读出 + Properties mappings = + PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader); + if (logger.isTraceEnabled()) { + logger.trace("Loaded NamespaceHandler mappings: " + mappings); + } + handlerMappings = new ConcurrentHashMap<>(mappings.size()); + // 转换成map结构 + CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings); + this.handlerMappings = handlerMappings; + } + catch (IOException ex) { + throw new IllegalStateException( + "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex); + } + } + } + } + return handlerMappings; + } + +``` + + + + + + + + + +## org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#resolve + +```java + @Override + @Nullable + public NamespaceHandler resolve(String namespaceUri) { + // 获取handlerMapping + Map handlerMappings = getHandlerMappings(); + // 从 handlerMapping 中获取类名 + 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); + // 调用init()方法,自定义类中实现 + namespaceHandler.init(); + // 放入缓存 + handlerMappings.put(namespaceUri, namespaceHandler); + // 返回自定义的 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); + } + } + } + +``` + +执行`init`方法 + +```java +public class UserNamespaceHandler extends NamespaceHandlerSupport { + @Override + public void init() { + registerBeanDefinitionParser("myUser", new UserBeanDefinitionParser()); + } +} +``` + +```java + /** + * Subclasses can call this to register the supplied {@link BeanDefinitionParser} to + * handle the specified element. The element name is the local (non-namespace qualified) + * name. + * + * 将标签名称,标签解析类放入 + */ + protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) { + this.parsers.put(elementName, parser); + } + +``` + + + +- 方法走完,回到开始的方法 + + ```java + /** + * Parse a custom element (outside of the default namespace). + * + * 自定义标签解析 + * + * @param ele the element to parse + * @param containingBd the containing bean definition (if any) + * @return the resulting bean definition + */ + @Nullable + public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { + // 自定义标签解析 + String namespaceUri = getNamespaceURI(ele); + if (namespaceUri == null) { + return null; + } + // 根据命名空间获取处理类 + // org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve + 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)); + } + + ``` + + + + + + + + + +## org.springframework.beans.factory.xml.NamespaceHandler#parse + +- `org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse` + + ```java + @Override + @Nullable + public BeanDefinition parse(Element element, ParserContext parserContext) { + BeanDefinitionParser parser = findParserForElement(element, parserContext); + return (parser != null ? parser.parse(element, parserContext) : null); + } + + ``` + +### org.springframework.beans.factory.xml.NamespaceHandlerSupport#findParserForElement + +```java + @Nullable + private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { + // 获取标签名称 + String localName = parserContext.getDelegate().getLocalName(element); + // 在map中获取对应的标签解析类 + BeanDefinitionParser parser = this.parsers.get(localName); + // 空报错 + if (parser == null) { + parserContext.getReaderContext().fatal( + "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); + } + // 不为空返回 + return parser; + } + +``` + + + +### org.springframework.beans.factory.xml.BeanDefinitionParser#parse + +- `org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parse` + +```java + public final BeanDefinition parse(Element element, ParserContext parserContext) { + /** + * {@link AbstractSingleBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)} + */ + AbstractBeanDefinition definition = parseInternal(element, parserContext); + + + } +``` + +### org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#parseInternal + +```java +@Override + protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); + String parentName = getParentName(element); + if (parentName != null) { + builder.getRawBeanDefinition().setParentName(parentName); + } + // 调用自己实现的方法 com.huifer.source.spring.parser.UserBeanDefinitionParser.getBeanClass + Class> beanClass = getBeanClass(element); + if (beanClass != null) { + builder.getRawBeanDefinition().setBeanClass(beanClass); + } + else { + // getBeanClassName 同样也是可以在自定义的解析类中实现 + 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. + // 设置scope + builder.setScope(containingBd.getScope()); + } + if (parserContext.isDefaultLazyInit()) { + // Default-lazy-init applies to custom bean definitions as well. + // 设置 lazy-init + builder.setLazyInit(true); + } + + // 执行解析方法,在自定义解析类中存在com.huifer.source.spring.parser.UserBeanDefinitionParser.doParse + doParse(element, parserContext, builder); + return builder.getBeanDefinition(); + } +``` + + + + + +执行`com.huifer.source.spring.parser.UserBeanDefinitionParser#doParse` + +```JAVA +@Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + // 获取 userName 标签属性值 + String name = element.getAttribute("userName"); + // 获取 emailAddress 标签属性值 + String address = element.getAttribute("emailAddress"); + + if (StringUtils.hasText(name)) { + builder.addPropertyValue("userName", name); + } + if (StringUtils.hasText(address)) { + builder.addPropertyValue("emailAddress", address); + } + } +``` + + + + + diff --git a/images/spring/image-20200109084131415.png b/images/spring/image-20200109084131415.png new file mode 100644 index 0000000..6d99aa1 Binary files /dev/null and b/images/spring/image-20200109084131415.png differ diff --git a/images/spring/image-20200109085606240.png b/images/spring/image-20200109085606240.png new file mode 100644 index 0000000..61883bf Binary files /dev/null and b/images/spring/image-20200109085606240.png differ diff --git a/images/spring/image-20200109090456547.png b/images/spring/image-20200109090456547.png new file mode 100644 index 0000000..19e745c Binary files /dev/null and b/images/spring/image-20200109090456547.png differ diff --git a/images/spring/image-20200109090655157.png b/images/spring/image-20200109090655157.png new file mode 100644 index 0000000..97c431c Binary files /dev/null and b/images/spring/image-20200109090655157.png differ diff --git a/images/spring/image-20200109091216505.png b/images/spring/image-20200109091216505.png new file mode 100644 index 0000000..cbc2d48 Binary files /dev/null and b/images/spring/image-20200109091216505.png differ diff --git a/images/spring/image-20200109092801572.png b/images/spring/image-20200109092801572.png new file mode 100644 index 0000000..043a9ca Binary files /dev/null and b/images/spring/image-20200109092801572.png differ diff --git a/images/spring/image-20200109093242494.png b/images/spring/image-20200109093242494.png new file mode 100644 index 0000000..8d8077f Binary files /dev/null and b/images/spring/image-20200109093242494.png differ diff --git a/images/spring/image-20200109094032421.png b/images/spring/image-20200109094032421.png new file mode 100644 index 0000000..a8dcfb1 Binary files /dev/null and b/images/spring/image-20200109094032421.png differ diff --git a/images/spring/image-20200109094649217.png b/images/spring/image-20200109094649217.png new file mode 100644 index 0000000..2c2b1f2 Binary files /dev/null and b/images/spring/image-20200109094649217.png differ diff --git a/images/spring/image-20200109094654409.png b/images/spring/image-20200109094654409.png new file mode 100644 index 0000000..2c2b1f2 Binary files /dev/null and b/images/spring/image-20200109094654409.png differ diff --git a/images/spring/image-20200109150841916.png b/images/spring/image-20200109150841916.png new file mode 100644 index 0000000..c85d445 Binary files /dev/null and b/images/spring/image-20200109150841916.png differ diff --git a/images/spring/image-20200110093044672.png b/images/spring/image-20200110093044672.png new file mode 100644 index 0000000..514b59c Binary files /dev/null and b/images/spring/image-20200110093044672.png differ diff --git a/images/spring/image-20200115083744268.png b/images/spring/image-20200115083744268.png new file mode 100644 index 0000000..8a465cd Binary files /dev/null and b/images/spring/image-20200115083744268.png differ diff --git a/images/spring/image-20200115084031725.png b/images/spring/image-20200115084031725.png new file mode 100644 index 0000000..6742458 Binary files /dev/null and b/images/spring/image-20200115084031725.png differ diff --git a/images/spring/image-20200115093602651.png b/images/spring/image-20200115093602651.png new file mode 100644 index 0000000..fa04a3c Binary files /dev/null and b/images/spring/image-20200115093602651.png differ diff --git a/images/spring/image-20200115105941265.png b/images/spring/image-20200115105941265.png new file mode 100644 index 0000000..88c456b Binary files /dev/null and b/images/spring/image-20200115105941265.png differ diff --git a/images/spring/image-20200115141708702.png b/images/spring/image-20200115141708702.png new file mode 100644 index 0000000..2c1ada0 Binary files /dev/null and b/images/spring/image-20200115141708702.png differ diff --git a/images/spring/image-20200115143315633.png b/images/spring/image-20200115143315633.png new file mode 100644 index 0000000..6edee36 Binary files /dev/null and b/images/spring/image-20200115143315633.png differ diff --git a/images/spring/image-20200115143456554.png b/images/spring/image-20200115143456554.png new file mode 100644 index 0000000..d19ba94 Binary files /dev/null and b/images/spring/image-20200115143456554.png differ diff --git a/images/spring/image-20200116085344737.png b/images/spring/image-20200116085344737.png new file mode 100644 index 0000000..6f39a30 Binary files /dev/null and b/images/spring/image-20200116085344737.png differ diff --git a/images/spring/image-20200116085423073.png b/images/spring/image-20200116085423073.png new file mode 100644 index 0000000..c40cad2 Binary files /dev/null and b/images/spring/image-20200116085423073.png differ diff --git a/images/spring/image-20200116085726577.png b/images/spring/image-20200116085726577.png new file mode 100644 index 0000000..31a3481 Binary files /dev/null and b/images/spring/image-20200116085726577.png differ diff --git a/images/spring/image-20200116085737632.png b/images/spring/image-20200116085737632.png new file mode 100644 index 0000000..ae8f4cb Binary files /dev/null and b/images/spring/image-20200116085737632.png differ diff --git a/images/spring/image-20200116085927359.png b/images/spring/image-20200116085927359.png new file mode 100644 index 0000000..7a02538 Binary files /dev/null and b/images/spring/image-20200116085927359.png differ diff --git a/images/spring/image-20200116092259944.png b/images/spring/image-20200116092259944.png new file mode 100644 index 0000000..0d20a5a Binary files /dev/null and b/images/spring/image-20200116092259944.png differ diff --git a/images/spring/image-20200116141838601.png b/images/spring/image-20200116141838601.png new file mode 100644 index 0000000..e4ee61b Binary files /dev/null and b/images/spring/image-20200116141838601.png differ diff --git a/images/spring/image-20200116141932486.png b/images/spring/image-20200116141932486.png new file mode 100644 index 0000000..8e06086 Binary files /dev/null and b/images/spring/image-20200116141932486.png differ diff --git a/images/spring/image-20200119085346675.png b/images/spring/image-20200119085346675.png new file mode 100644 index 0000000..2c23ebb Binary files /dev/null and b/images/spring/image-20200119085346675.png differ diff --git a/images/spring/image-20200119085655734.png b/images/spring/image-20200119085655734.png new file mode 100644 index 0000000..18bf79e Binary files /dev/null and b/images/spring/image-20200119085655734.png differ diff --git a/images/spring/image-20200119101017989.png b/images/spring/image-20200119101017989.png new file mode 100644 index 0000000..c8b3ad9 Binary files /dev/null and b/images/spring/image-20200119101017989.png differ diff --git a/images/spring/image-20200119101026726.png b/images/spring/image-20200119101026726.png new file mode 100644 index 0000000..14b6c3e Binary files /dev/null and b/images/spring/image-20200119101026726.png differ diff --git a/images/spring/image-20200119101107820.png b/images/spring/image-20200119101107820.png new file mode 100644 index 0000000..e2546cb Binary files /dev/null and b/images/spring/image-20200119101107820.png differ diff --git a/images/spring/image-20200119101516591.png b/images/spring/image-20200119101516591.png new file mode 100644 index 0000000..4236551 Binary files /dev/null and b/images/spring/image-20200119101516591.png differ
+ * 自定义标签解析 + * + * @param ele the element to parse + * @param containingBd the containing bean definition (if any) + * @return the resulting bean definition + */ + @Nullable + public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { + // 自定义标签解析 + String namespaceUri = getNamespaceURI(ele); + if (namespaceUri == null) { + return null; + } + // 根据命名空间获取处理类 + // org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve + 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)); + } + + ``` + + + + + + + + + +## org.springframework.beans.factory.xml.NamespaceHandler#parse + +- `org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse` + + ```java + @Override + @Nullable + public BeanDefinition parse(Element element, ParserContext parserContext) { + BeanDefinitionParser parser = findParserForElement(element, parserContext); + return (parser != null ? parser.parse(element, parserContext) : null); + } + + ``` + +### org.springframework.beans.factory.xml.NamespaceHandlerSupport#findParserForElement + +```java + @Nullable + private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { + // 获取标签名称 + String localName = parserContext.getDelegate().getLocalName(element); + // 在map中获取对应的标签解析类 + BeanDefinitionParser parser = this.parsers.get(localName); + // 空报错 + if (parser == null) { + parserContext.getReaderContext().fatal( + "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); + } + // 不为空返回 + return parser; + } + +``` + + + +### org.springframework.beans.factory.xml.BeanDefinitionParser#parse + +- `org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parse` + +```java + public final BeanDefinition parse(Element element, ParserContext parserContext) { + /** + * {@link AbstractSingleBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)} + */ + AbstractBeanDefinition definition = parseInternal(element, parserContext); + + + } +``` + +### org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#parseInternal + +```java +@Override + protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); + String parentName = getParentName(element); + if (parentName != null) { + builder.getRawBeanDefinition().setParentName(parentName); + } + // 调用自己实现的方法 com.huifer.source.spring.parser.UserBeanDefinitionParser.getBeanClass + Class> beanClass = getBeanClass(element); + if (beanClass != null) { + builder.getRawBeanDefinition().setBeanClass(beanClass); + } + else { + // getBeanClassName 同样也是可以在自定义的解析类中实现 + 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. + // 设置scope + builder.setScope(containingBd.getScope()); + } + if (parserContext.isDefaultLazyInit()) { + // Default-lazy-init applies to custom bean definitions as well. + // 设置 lazy-init + builder.setLazyInit(true); + } + + // 执行解析方法,在自定义解析类中存在com.huifer.source.spring.parser.UserBeanDefinitionParser.doParse + doParse(element, parserContext, builder); + return builder.getBeanDefinition(); + } +``` + + + + + +执行`com.huifer.source.spring.parser.UserBeanDefinitionParser#doParse` + +```JAVA +@Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + // 获取 userName 标签属性值 + String name = element.getAttribute("userName"); + // 获取 emailAddress 标签属性值 + String address = element.getAttribute("emailAddress"); + + if (StringUtils.hasText(name)) { + builder.addPropertyValue("userName", name); + } + if (StringUtils.hasText(address)) { + builder.addPropertyValue("emailAddress", address); + } + } +``` + + + + + diff --git a/docs/Spring/JDBC/Spring-jdbc.md b/docs/Spring/JDBC/Spring-jdbc.md new file mode 100644 index 0000000..47b46b3 --- /dev/null +++ b/docs/Spring/JDBC/Spring-jdbc.md @@ -0,0 +1,522 @@ +# Spring JDBC +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) + + + +## 环境搭建 + +- 依赖 + + ```gradle + compile(project(":spring-jdbc")) + compile group: 'com.alibaba', name: 'druid', version: '1.1.21' + compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.47' + ``` + +- db配置 + + ```properties + jdbc.url= + jdbc.driverClass= + jdbc.username= + jdbc.password= + ``` + +- 实体对象 + + ```JAVA + public class HsLog { + private Integer id; + + private String source; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + } + ``` + + + +- DAO + + ```JAVA + public interface HsLogDao { + List findAll(); + + void save(HsLog hsLog); + } + + ``` + + + +- 实现类 + + ```JAVA + public class HsLogDaoImpl extends JdbcDaoSupport implements HsLogDao { + + + @Override + public List findAll() { + return this.getJdbcTemplate().query("select * from hs_log", new HsLogRowMapper()); + + } + + @Override + public void save(HsLog hsLog) { + this.getJdbcTemplate().update("insert into hs_log (SOURCE) values(?)" + , new Object[]{ + hsLog.getSource(), + } + + ); + } + + class HsLogRowMapper implements RowMapper { + + public HsLog mapRow(ResultSet rs, int rowNum) throws SQLException { + + HsLog log = new HsLog(); + log.setId(rs.getInt("id")); + log.setSource(rs.getString("source")); + return log; + } + + } + } + + ``` + + + +- xml + + ```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ``` + +- 运行方法 + + ```JAVA + + public class SpringJDBCSourceCode { + public static void main(String[] args) { + ApplicationContext applicationContext = new ClassPathXmlApplicationContext("JDBC-demo.xml"); + HsLogDaoImpl bean = applicationContext.getBean(HsLogDaoImpl.class); + System.out.println(bean.findAll()); + HsLog hsLog = new HsLog(); + hsLog.setSource("jlkjll"); + bean.save(hsLog); + + } + } + + ``` + + + + + + + +## 链接对象构造 + +`Connection con = DataSourceUtils.getConnection(obtainDataSource());` + +```java + public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException { + try { + return doGetConnection(dataSource); + } + catch (SQLException ex) { + throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection", ex); + } + catch (IllegalStateException ex) { + throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection: " + ex.getMessage()); + } + } + +``` + +### org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection + +```java + public static Connection doGetConnection(DataSource dataSource) throws SQLException { + Assert.notNull(dataSource, "No DataSource specified"); + + ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource); + if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) { + conHolder.requested(); + if (!conHolder.hasConnection()) { + logger.debug("Fetching resumed JDBC Connection from DataSource"); + // 设置连接对象 + conHolder.setConnection(fetchConnection(dataSource)); + } + return conHolder.getConnection(); + } + // Else we either got no holder or an empty thread-bound holder here. + + logger.debug("Fetching JDBC Connection from DataSource"); + // 获取链接 + Connection con = fetchConnection(dataSource); + + // 当前线程支持同步 + if (TransactionSynchronizationManager.isSynchronizationActive()) { + try { + // Use same Connection for further JDBC actions within the transaction. + // Thread-bound object will get removed by synchronization at transaction completion. + // 在同一个事物中使用同一个链接对象 + ConnectionHolder holderToUse = conHolder; + if (holderToUse == null) { + holderToUse = new ConnectionHolder(con); + } + else { + holderToUse.setConnection(con); + } + // 记录链接数量 + holderToUse.requested(); + TransactionSynchronizationManager.registerSynchronization( + new ConnectionSynchronization(holderToUse, dataSource)); + holderToUse.setSynchronizedWithTransaction(true); + if (holderToUse != conHolder) { + TransactionSynchronizationManager.bindResource(dataSource, holderToUse); + } + } + catch (RuntimeException ex) { + // Unexpected exception from external delegation call -> close Connection and rethrow. + releaseConnection(con, dataSource); + throw ex; + } + } + + return con; + } + +``` + + + + + +## 释放资源 + +`releaseConnection(con, dataSource);` + +- `org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection` + +```JAVA + public static void releaseConnection(@Nullable Connection con, @Nullable DataSource dataSource) { + try { + doReleaseConnection(con, dataSource); + } + catch (SQLException ex) { + logger.debug("Could not close JDBC Connection", ex); + } + catch (Throwable ex) { + logger.debug("Unexpected exception on closing JDBC Connection", ex); + } + } + +``` + +```java +public static void doReleaseConnection(@Nullable Connection con, @Nullable DataSource dataSource) throws SQLException { + if (con == null) { + return; + } + if (dataSource != null) { + ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource); + if (conHolder != null && connectionEquals(conHolder, con)) { + // It's the transactional Connection: Don't close it. + // 连接数-1 + conHolder.released(); + return; + } + } + // 处理其他情况 + doCloseConnection(con, dataSource); + } +``` + + + + + +### org.springframework.transaction.support.ResourceHolderSupport + +链接数 + +```JAVA + /** + * Increase the reference count by one because the holder has been requested + * (i.e. someone requested the resource held by it). + */ + public void requested() { + this.referenceCount++; + } + + /** + * Decrease the reference count by one because the holder has been released + * (i.e. someone released the resource held by it). + */ + public void released() { + this.referenceCount--; + } +``` + + + + + + + +## 查询解析 + +### org.springframework.jdbc.core.JdbcTemplate + +```XML + + + + +``` +- 从配置中可以知道 JdbcTemplate 需要 dataSource 属性, 就从这里开始讲起 +- `org.springframework.jdbc.support.JdbcAccessor.setDataSource`, 这段代码就只做了赋值操作(依赖注入) +```java +public void setDataSource(@Nullable DataSource dataSource) { + this.dataSource = dataSource; + } +``` +- 下面`hsLogDao`也是依赖注入本篇不做详细讲述。 + + + +### org.springframework.jdbc.core.JdbcTemplate#query(java.lang.String, org.springframework.jdbc.core.RowMapper) + +```java + @Override + public List findAll() { + return this.getJdbcTemplate().query("select * from hs_log", new HsLogRowMapper()); + } + +``` + +```java + @Override + @Nullable + public T query(final String sql, final ResultSetExtractor rse) throws DataAccessException { + Assert.notNull(sql, "SQL must not be null"); + Assert.notNull(rse, "ResultSetExtractor must not be null"); + if (logger.isDebugEnabled()) { + logger.debug("Executing SQL query [" + sql + "]"); + } + + /** + * Callback to execute the query. + */ + class QueryStatementCallback implements StatementCallback, SqlProvider { + @Override + @Nullable + public T doInStatement(Statement stmt) throws SQLException { + ResultSet rs = null; + try { + // 执行sql + rs = stmt.executeQuery(sql); + // 1. org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData + return rse.extractData(rs); + } + finally { + JdbcUtils.closeResultSet(rs); + } + } + + @Override + public String getSql() { + return sql; + } + } + + return execute(new QueryStatementCallback()); + } + +``` + +```java + @Override + @Nullable + public T execute(StatementCallback action) throws DataAccessException { + Assert.notNull(action, "Callback object must not be null"); + + Connection con = DataSourceUtils.getConnection(obtainDataSource()); + Statement stmt = null; + try { + stmt = con.createStatement(); + applyStatementSettings(stmt); + // 执行 + T result = action.doInStatement(stmt); + handleWarnings(stmt); + return result; + } + catch (SQLException ex) { + // Release Connection early, to avoid potential connection pool deadlock + // in the case when the exception translator hasn't been initialized yet. + String sql = getSql(action); + JdbcUtils.closeStatement(stmt); + stmt = null; + DataSourceUtils.releaseConnection(con, getDataSource()); + con = null; + throw translateException("StatementCallback", sql, ex); + } + finally { + JdbcUtils.closeStatement(stmt); + DataSourceUtils.releaseConnection(con, getDataSource()); + } + } +``` + +```JAVA + @Override + public List extractData(ResultSet rs) throws SQLException { + List results = (this.rowsExpected > 0 ? new ArrayList<>(this.rowsExpected) : new ArrayList<>()); + int rowNum = 0; + while (rs.next()) { + // 调用自定义的 rowMapper 进行数据处理 + T t = this.rowMapper.mapRow(rs, rowNum++); + results.add(t); + } + return results; + } + +``` + + + +这样就可以获取到了 + +方法`result`没有什么操作直接返回即可 + +```java + private static T result(@Nullable T result) { + Assert.state(result != null, "No result"); + return result; + } +``` + + + + + + + +## 插入解析 + +```java +@Override + public void save(HsLog hsLog) { + this.getJdbcTemplate().update("insert into hs_log (SOURCE) values(?)" + , new Object[]{ + hsLog.getSource(), + } + + ); + } +``` + +`org.springframework.jdbc.core.JdbcTemplate#update(org.springframework.jdbc.core.PreparedStatementCreator, org.springframework.jdbc.core.PreparedStatementSetter)` + +```java + protected int update(final PreparedStatementCreator psc, @Nullable final PreparedStatementSetter pss) + throws DataAccessException { + + logger.debug("Executing prepared SQL update"); + + return updateCount(execute(psc, ps -> { + try { + if (pss != null) { + // 设置请求参数 + pss.setValues(ps); + } + int rows = ps.executeUpdate(); + if (logger.isTraceEnabled()) { + logger.trace("SQL update affected " + rows + " rows"); + } + return rows; + } + finally { + if (pss instanceof ParameterDisposer) { + ((ParameterDisposer) pss).cleanupParameters(); + } + } + })); + } + +``` + + + + + diff --git a/docs/Spring/Spring5新特性/Spring-spring-components.md b/docs/Spring/Spring5新特性/Spring-spring-components.md new file mode 100644 index 0000000..10bef93 --- /dev/null +++ b/docs/Spring/Spring5新特性/Spring-spring-components.md @@ -0,0 +1,124 @@ +# Spring5 新特性 - spring.components +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) + + +## 解析 +- 相关类: `org.springframework.context.index.CandidateComponentsIndexLoader` +- 测试用例: `org.springframework.context.annotation.ClassPathScanningCandidateComponentProviderTests.defaultsWithIndex`,`org.springframework.context.index.CandidateComponentsIndexLoaderTests` +- `CandidateComponentsIndexLoader`是怎么找出来的,全文搜索`spring.components` +### 使用介绍 +- 下面是从`resources/example/scannable/spring.components`测试用例中复制过来的,从中可以发现等号左侧放的是我们写的组件,等号右边是属于什么组件 +``` +example.scannable.AutowiredQualifierFooService=example.scannable.FooService +example.scannable.DefaultNamedComponent=org.springframework.stereotype.Component +example.scannable.NamedComponent=org.springframework.stereotype.Component +example.scannable.FooService=example.scannable.FooService +example.scannable.FooServiceImpl=org.springframework.stereotype.Component,example.scannable.FooService +example.scannable.ScopedProxyTestBean=example.scannable.FooService +example.scannable.StubFooDao=org.springframework.stereotype.Component +example.scannable.NamedStubDao=org.springframework.stereotype.Component +example.scannable.ServiceInvocationCounter=org.springframework.stereotype.Component +example.scannable.sub.BarComponent=org.springframework.stereotype.Component +``` + +### debug +- 入口 `org.springframework.context.index.CandidateComponentsIndexLoader.loadIndex` +```java + @Nullable + public static CandidateComponentsIndex loadIndex(@Nullable ClassLoader classLoader) { + ClassLoader classLoaderToUse = classLoader; + if (classLoaderToUse == null) { + classLoaderToUse = CandidateComponentsIndexLoader.class.getClassLoader(); + } + return cache.computeIfAbsent(classLoaderToUse, CandidateComponentsIndexLoader::doLoadIndex); + } + +``` +```java + /** + * 解析 META-INF/spring.components 文件 + * @param classLoader + * @return + */ + @Nullable + private static CandidateComponentsIndex doLoadIndex(ClassLoader classLoader) { + if (shouldIgnoreIndex) { + return null; + } + + try { + Enumeration urls = classLoader.getResources(COMPONENTS_RESOURCE_LOCATION); + if (!urls.hasMoreElements()) { + return null; + } + List result = new ArrayList<>(); + while (urls.hasMoreElements()) { + URL url = urls.nextElement(); + // 读取META-INF/spring.components文件转换成map对象 + Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url)); + result.add(properties); + } + if (logger.isDebugEnabled()) { + logger.debug("Loaded " + result.size() + "] index(es)"); + } + int totalCount = result.stream().mapToInt(Properties::size).sum(); + // 查看CandidateComponentsIndex方法 + return (totalCount > 0 ? new CandidateComponentsIndex(result) : null); + } + catch (IOException ex) { + throw new IllegalStateException("Unable to load indexes from location [" + + COMPONENTS_RESOURCE_LOCATION + "]", ex); + } + } + +``` + +```java + CandidateComponentsIndex(List content) { + this.index = parseIndex(content); + } + + /** + * 解析 MATE-INF\spring.components 转换成 map + * + * @param content + * @return + */ + private static MultiValueMap parseIndex(List content) { + MultiValueMap index = new LinkedMultiValueMap<>(); + for (Properties entry : content) { + entry.forEach((type, values) -> { + String[] stereotypes = ((String) values).split(","); + for (String stereotype : stereotypes) { + index.add(stereotype, new Entry((String) type)); + } + }); + } + return index; + } +``` + + + + + + +- 该类给`org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents`提供了帮助 + +```java + public Set findCandidateComponents(String basePackage) { + // 扫描 + /** + * if 测试用例: {@link org.springframework.context.annotation.ClassPathScanningCandidateComponentProviderTests#defaultsWithIndex()} + * 解析 spring.components文件 + */ + if (this.componentsIndex != null && indexSupportsIncludeFilters()) { + return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); + } + else { + return scanCandidateComponents(basePackage); + } + } + +``` \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-AnnotationUtils.md b/docs/Spring/clazz/Spring-AnnotationUtils.md new file mode 100644 index 0000000..0da8161 --- /dev/null +++ b/docs/Spring/clazz/Spring-AnnotationUtils.md @@ -0,0 +1,518 @@ +# Spring AnnotationUtils +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) +- `org.springframework.core.annotation.AnnotationUtils`提供了注解相关的方法 + 1. getAnnotation: 获取注解 + 1. findAnnotation: 寻找注解 + 1. getValue: 获取属性值 + 1. getDefaultValue: 获取默认值 + + +## getAnnotation +- 测试用例如下 +```java + @Test + public void findMethodAnnotationOnLeaf() throws Exception { + Method m = Leaf.class.getMethod("annotatedOnLeaf"); + assertNotNull(m.getAnnotation(Order.class)); + assertNotNull(getAnnotation(m, Order.class)); + assertNotNull(findAnnotation(m, Order.class)); + } + +``` +- `org.springframework.core.annotation.AnnotationUtils.getAnnotation(java.lang.reflect.Method, java.lang.Class)` +```java + /** + * Get a single {@link Annotation} of {@code annotationType} from the + * supplied {@link Method}, where the annotation is either present + * or meta-present on the method. + * Correctly handles bridge {@link Method Methods} generated by the compiler. + * Note that this method supports only a single level of meta-annotations. + * For support for arbitrary levels of meta-annotations, use + * {@link #findAnnotation(Method, Class)} instead. + * + * @param method the method to look for annotations on + * 被检查的函数 + * @param annotationType the annotation type to look for + * 需要检测的注解类型 + * @return the first matching annotation, or {@code null} if not found + * @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method) + * @see #getAnnotation(AnnotatedElement, Class) + */ + @Nullable + public static A getAnnotation(Method method, Class annotationType) { + // 函数 + Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method); + // 强制转换 + return getAnnotation((AnnotatedElement) resolvedMethod, annotationType); + } + +``` +- method + +  + +- annotationType + +  + +```java + @Nullable + public static A getAnnotation(AnnotatedElement annotatedElement, Class annotationType) { + try { + // 获取注解 + A annotation = annotatedElement.getAnnotation(annotationType); + if (annotation == null) { + for (Annotation metaAnn : annotatedElement.getAnnotations()) { + annotation = metaAnn.annotationType().getAnnotation(annotationType); + if (annotation != null) { + break; + } + } + } + return (annotation != null ? synthesizeAnnotation(annotation, annotatedElement) : null); + } catch (Throwable ex) { + handleIntrospectionFailure(annotatedElement, ex); + return null; + } + } + +``` +- `org.springframework.core.annotation.AnnotationUtils.synthesizeAnnotation(A, java.lang.reflect.AnnotatedElement)` +```java + public static A synthesizeAnnotation( + A annotation, @Nullable AnnotatedElement annotatedElement) { + + return synthesizeAnnotation(annotation, (Object) annotatedElement); + } + +``` +```java + /** + * 注解是否存在别名,没有直接返回 + * + * @param annotation 注解 + * @param annotatedElement 函数 + * @param + * @return + */ + @SuppressWarnings("unchecked") + static A synthesizeAnnotation(A annotation, @Nullable Object annotatedElement) { + if (annotation instanceof SynthesizedAnnotation || hasPlainJavaAnnotationsOnly(annotatedElement)) { + return annotation; + } + // 具体的注解 + Class extends Annotation> annotationType = annotation.annotationType(); + if (!isSynthesizable(annotationType)) { + return annotation; + } + + DefaultAnnotationAttributeExtractor attributeExtractor = + new DefaultAnnotationAttributeExtractor(annotation, annotatedElement); + InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor); + + // Can always expose Spring's SynthesizedAnnotation marker since we explicitly check for a + // synthesizable annotation before (which needs to declare @AliasFor from the same package) + Class>[] exposedInterfaces = new Class>[]{annotationType, SynthesizedAnnotation.class}; + return (A) Proxy.newProxyInstance(annotation.getClass().getClassLoader(), exposedInterfaces, handler); + } + +``` +-`org.springframework.core.annotation.AnnotationUtils.isSynthesizable` +```java + @SuppressWarnings("unchecked") + private static boolean isSynthesizable(Class extends Annotation> annotationType) { + if (hasPlainJavaAnnotationsOnly(annotationType)) { + return false; + } + // 从缓存中获取当前注解,不存在null + Boolean synthesizable = synthesizableCache.get(annotationType); + if (synthesizable != null) { + return synthesizable; + } + + synthesizable = Boolean.FALSE; + for (Method attribute : getAttributeMethods(annotationType)) { + if (!getAttributeAliasNames(attribute).isEmpty()) { + synthesizable = Boolean.TRUE; + break; + } + // 获取返回值类型 + Class> returnType = attribute.getReturnType(); + + // 根据返回值做不同处理 + if (Annotation[].class.isAssignableFrom(returnType)) { + Class extends Annotation> nestedAnnotationType = + (Class extends Annotation>) returnType.getComponentType(); + if (isSynthesizable(nestedAnnotationType)) { + synthesizable = Boolean.TRUE; + break; + } + } else if (Annotation.class.isAssignableFrom(returnType)) { + Class extends Annotation> nestedAnnotationType = (Class extends Annotation>) returnType; + if (isSynthesizable(nestedAnnotationType)) { + synthesizable = Boolean.TRUE; + break; + } + } + } + + synthesizableCache.put(annotationType, synthesizable); + return synthesizable; + } + +``` + +- `org.springframework.core.annotation.AnnotationUtils#getAttributeMethods` + +```java + static List getAttributeMethods(Class extends Annotation> annotationType) { + List methods = attributeMethodsCache.get(annotationType); + if (methods != null) { + return methods; + } + + methods = new ArrayList<>(); + // annotationType.getDeclaredMethods() 获取注解中的方法 + for (Method method : annotationType.getDeclaredMethods()) { + if (isAttributeMethod(method)) { + ReflectionUtils.makeAccessible(method); + methods.add(method); + } + } + + // 缓存 key:注解,value:函数列表 + attributeMethodsCache.put(annotationType, methods); + // 函数列表 + return methods; + } + +``` + +- `org.springframework.core.annotation.AnnotationUtils#isAttributeMethod` + +```java + /** + * Determine if the supplied {@code method} is an annotation attribute method. + * + * 做3个判断 + * + * 函数不为空(method != null) + * 参数列表是不是空(method.getParameterCount() == 0) + * 返回类型不是void(method.getReturnType() != void.class) + * + * + * @param method the method to check + * @return {@code true} if the method is an attribute method + * @since 4.2 + */ + static boolean isAttributeMethod(@Nullable Method method) { + return (method != null && method.getParameterCount() == 0 && method.getReturnType() != void.class); + } + +``` + +- `org.springframework.util.ReflectionUtils#makeAccessible(java.lang.reflect.Method)` + +```java +@SuppressWarnings("deprecation") // on JDK 9 + public static void makeAccessible(Method method) { + // 1. 方法修饰符是不是public + // 2. 注解是不是public + // 3. 是否重写 + if ((!Modifier.isPublic(method.getModifiers()) || + !Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible()) { + method.setAccessible(true); + } + } +``` + +处理结果 + + + + + +处理结果和Order定义相同 + +```java +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) +@Documented +public @interface Order { + + /** + * The order value. + * Default is {@link Ordered#LOWEST_PRECEDENCE}. + * + * 启动顺序,默认integer最大值 + * @see Ordered#getOrder() + */ + int value() default Ordered.LOWEST_PRECEDENCE; + +} +``` + + + +最终返回 + + + + + + + + + + + +## findAnnotation + +- `org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.Method, java.lang.Class)` + + ```java + @SuppressWarnings("unchecked") + @Nullable + public static A findAnnotation(Method method, @Nullable Class annotationType) { + Assert.notNull(method, "Method must not be null"); + if (annotationType == null) { + return null; + } + // 创建注解缓存,key:被扫描的函数,value:注解 + AnnotationCacheKey cacheKey = new AnnotationCacheKey(method, annotationType); + // 从findAnnotationCache获取缓存 + A result = (A) findAnnotationCache.get(cacheKey); + + if (result == null) { + Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method); + // 寻找注解 + result = findAnnotation((AnnotatedElement) resolvedMethod, annotationType); + if (result == null) { + result = searchOnInterfaces(method, annotationType, method.getDeclaringClass().getInterfaces()); + } + + Class> clazz = method.getDeclaringClass(); + while (result == null) { + clazz = clazz.getSuperclass(); + if (clazz == null || clazz == Object.class) { + break; + } + Set annotatedMethods = getAnnotatedMethodsInBaseType(clazz); + if (!annotatedMethods.isEmpty()) { + for (Method annotatedMethod : annotatedMethods) { + if (isOverride(method, annotatedMethod)) { + Method resolvedSuperMethod = BridgeMethodResolver.findBridgedMethod(annotatedMethod); + result = findAnnotation((AnnotatedElement) resolvedSuperMethod, annotationType); + if (result != null) { + break; + } + } + } + } + if (result == null) { + result = searchOnInterfaces(method, annotationType, clazz.getInterfaces()); + } + } + + if (result != null) { + // 处理注解 + result = synthesizeAnnotation(result, method); + // 添加缓存 + findAnnotationCache.put(cacheKey, result); + } + } + // 返回 + return result; + } + + ``` + + + +- `org.springframework.core.annotation.AnnotationUtils.AnnotationCacheKey` + + ```java + private static final class AnnotationCacheKey implements Comparable { + + /** + * 带有注解的函数或者类 + */ + private final AnnotatedElement element; + + /** + * 注解 + */ + private final Class extends Annotation> annotationType; + + public AnnotationCacheKey(AnnotatedElement element, Class extends Annotation> annotationType) { + this.element = element; + this.annotationType = annotationType; + } + + } + ``` + + + +- `org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.AnnotatedElement, java.lang.Class)` + + ```java + @Nullable + public static A findAnnotation( + AnnotatedElement annotatedElement, @Nullable Class annotationType) { + // 注解类型不为空 + if (annotationType == null) { + return null; + } + + // Do NOT store result in the findAnnotationCache since doing so could break + // findAnnotation(Class, Class) and findAnnotation(Method, Class). + // 寻找注解 + A ann = findAnnotation(annotatedElement, annotationType, new HashSet<>()); + return (ann != null ? synthesizeAnnotation(ann, annotatedElement) : null); + } + + ``` + + + + + +- `org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.AnnotatedElement, java.lang.Class, java.util.Set)` + + ```java + @Nullable + private static A findAnnotation( + AnnotatedElement annotatedElement, Class annotationType, Set visited) { + try { + // 直接获取注解 + A annotation = annotatedElement.getDeclaredAnnotation(annotationType); + if (annotation != null) { + return annotation; + } + // 多级注解 + for (Annotation declaredAnn : getDeclaredAnnotations(annotatedElement)) { + Class extends Annotation> declaredType = declaredAnn.annotationType(); + // 注解是否 由java.lang.annotation提供 + if (!isInJavaLangAnnotationPackage(declaredType) && visited.add(declaredAnn)) { + annotation = findAnnotation((AnnotatedElement) declaredType, annotationType, visited); + if (annotation != null) { + return annotation; + } + } + } + } catch (Throwable ex) { + handleIntrospectionFailure(annotatedElement, ex); + } + return null; + } + + ``` + + + + + +- `synthesizeAnnotation`方法就不再重复一遍了可以看上文 + + + + + + + +## getValue + +- 测试用例 + + ```java + @Test + public void getValueFromAnnotation() throws Exception { + Method method = SimpleFoo.class.getMethod("something", Object.class); + Order order = findAnnotation(method, Order.class); + + assertEquals(1, getValue(order, VALUE)); + assertEquals(1, getValue(order)); + } + ``` + + + +- `org.springframework.core.annotation.AnnotationUtils#getValue(java.lang.annotation.Annotation, java.lang.String)` + +```java + @Nullable + public static Object getValue(@Nullable Annotation annotation, @Nullable String attributeName) { + if (annotation == null || !StringUtils.hasText(attributeName)) { + return null; + } + try { + // 根据attributeName获取注解对应函数 + Method method = annotation.annotationType().getDeclaredMethod(attributeName); + ReflectionUtils.makeAccessible(method); + // 反射执行方法 + return method.invoke(annotation); + } catch (NoSuchMethodException ex) { + return null; + } catch (InvocationTargetException ex) { + rethrowAnnotationConfigurationException(ex.getTargetException()); + throw new IllegalStateException("Could not obtain value for annotation attribute '" + + attributeName + "' in " + annotation, ex); + } catch (Throwable ex) { + handleIntrospectionFailure(annotation.getClass(), ex); + return null; + } + } + +``` + + + +```java + @Nullable + public static Object getValue(Annotation annotation) { + return getValue(annotation, VALUE); + } + +``` + + + + + + + +## getDefaultValue + +- `org.springframework.core.annotation.AnnotationUtils#getDefaultValue(java.lang.annotation.Annotation)` + + + +```java + @Nullable + public static Object getDefaultValue(Annotation annotation) { + return getDefaultValue(annotation, VALUE); + } + +``` + +```java + @Nullable + public static Object getDefaultValue( + @Nullable Class extends Annotation> annotationType, @Nullable String attributeName) { + + if (annotationType == null || !StringUtils.hasText(attributeName)) { + return null; + } + try { + // 直接获取defaultValue + return annotationType.getDeclaredMethod(attributeName).getDefaultValue(); + } catch (Throwable ex) { + handleIntrospectionFailure(annotationType, ex); + return null; + } + } + +``` + diff --git a/docs/Spring/clazz/Spring-BeanFactoryPostProcessor.md b/docs/Spring/clazz/Spring-BeanFactoryPostProcessor.md new file mode 100644 index 0000000..81fe47a --- /dev/null +++ b/docs/Spring/clazz/Spring-BeanFactoryPostProcessor.md @@ -0,0 +1,447 @@ +# Spring BeanFactoryPostProcessor +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) +- 作用: 定制或修改`BeanDefinition`的属性 + + +## Demo +```java +public class ChangeAttrBeanPostProcessor implements BeanFactoryPostProcessor { + private Set attr; + + public ChangeAttrBeanPostProcessor() { + attr = new HashSet<>(); + } + + public Set getAttr() { + return attr; + } + + public void setAttr(Set attr) { + this.attr = attr; + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames(); + for (String beanName : beanDefinitionNames) { + BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); + + StringValueResolver stringValueResolver = new StringValueResolver() { + @Override + public String resolveStringValue(String strVal) { + if (attr.contains(strVal)) { + return "隐藏属性"; + } + else { + return strVal; + } + } + }; + BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(stringValueResolver); + visitor.visitBeanDefinition(beanDefinition); + } + } +} +``` + +```java +public class BeanFactoryPostProcessorSourceCode { + public static void main(String[] args) { + ApplicationContext context = new ClassPathXmlApplicationContext("BeanFactoryPostProcessor-demo.xml"); + Apple apple = context.getBean("apple", Apple.class); + System.out.println(apple); + } +} +``` + +```xml + + + + + + hc + + + + + + + + +``` + + + +## 初始化 + +- `org.springframework.context.support.AbstractApplicationContext#refresh` + + ```JAVA + invokeBeanFactoryPostProcessors(beanFactory); + ``` + + ```JAVA + 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())); + } + } + + ``` + +- `org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List)` + + ```JAVA + public static void invokeBeanFactoryPostProcessors( + ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) { + + // Invoke BeanDefinitionRegistryPostProcessors first, if any. + Set processedBeans = new HashSet<>(); + // 判断是否为BeanDefinitionRegistry类 + if (beanFactory instanceof BeanDefinitionRegistry) { + BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; + // 存放 BeanFactoryPostProcessor + List regularPostProcessors = new ArrayList<>(); + // 存放 BeanDefinitionRegistryPostProcessor + List registryProcessors = new ArrayList<>(); + + // 2.首先处理入参中的beanFactoryPostProcessors + for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { + // 判断是否是BeanDefinitionRegistryPostProcessor + if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { + BeanDefinitionRegistryPostProcessor registryProcessor = + (BeanDefinitionRegistryPostProcessor) postProcessor; + // + registryProcessor.postProcessBeanDefinitionRegistry(registry); + // BeanDefinitionRegistryPostProcessor 添加 + // 执行 postProcessBeanFactory + registryProcessors.add(registryProcessor); + } + // 这部分else 内容就是 BeanFactoryPostProcessor + else { + // BeanFactoryPostProcessor 添加 + 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 currentRegistryProcessors = new ArrayList<>(); + + // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. + /** + * 调用实现{@link PriorityOrdered}\{@link BeanDefinitionRegistryPostProcessor} + * todo: 2020年1月16日 解析方法 + * {@link DefaultListableBeanFactory#getBeanNamesForType(java.lang.Class, boolean, boolean)} + */ + 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); + } + } + // 排序Order + 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! + // 配置文件中的 BeanFactoryPostProcessor 处理 + String[] postProcessorNames = + beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); + + // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, + // Ordered, and the rest. + List priorityOrderedPostProcessors = new ArrayList<>(); + List orderedPostProcessorNames = new ArrayList<>(); + List 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 orderedPostProcessors = new ArrayList<>(); + for (String postProcessorName : orderedPostProcessorNames) { + orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); + } + sortPostProcessors(orderedPostProcessors, beanFactory); + invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); + + // Finally, invoke all other BeanFactoryPostProcessors. + // 配置文件中自定义的 BeanFactoryPostProcessor 注册 + List nonOrderedPostProcessors = new ArrayList<>(); + 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(); + } + ``` + + + + + + + + + + + +## InstantiationAwareBeanPostProcessor + +```java + protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { + PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this); + } +``` + + + +```java + public static void registerBeanPostProcessors( + ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { + // 获取 BeanPostProcessor + 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. + // BeanPostProcessor 通过PriorityOrdered保证顺序 + List priorityOrderedPostProcessors = new ArrayList<>(); + // MergedBeanDefinitionPostProcessor + List internalPostProcessors = new ArrayList<>(); + // 有序的 BeanPostProcessor + List orderedPostProcessorNames = new ArrayList<>(); + // 无序的 BeanPostProcessor + List nonOrderedPostProcessorNames = new ArrayList<>(); + for (String ppName : postProcessorNames) { + if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { + BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); + priorityOrderedPostProcessors.add(pp); + // 类型判断放入相应的list + 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. + /** + * 有{@link org.springframework.core.annotation.Order} 相关操作 + */ + sortPostProcessors(priorityOrderedPostProcessors, beanFactory); + // 注册 BeanPostProcessor 和 PriorityOrdered 实现 + registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); + + // Next, register the BeanPostProcessors that implement Ordered. + List orderedPostProcessors = new ArrayList<>(); + for (String ppName : orderedPostProcessorNames) { + BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); + orderedPostProcessors.add(pp); + if (pp instanceof MergedBeanDefinitionPostProcessor) { + internalPostProcessors.add(pp); + } + } + sortPostProcessors(orderedPostProcessors, beanFactory); + // 注册 实现Order 和 BeanPostProcessor + registerBeanPostProcessors(beanFactory, orderedPostProcessors); + + // Now, register all regular BeanPostProcessors. + List nonOrderedPostProcessors = new ArrayList<>(); + for (String ppName : nonOrderedPostProcessorNames) { + BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); + nonOrderedPostProcessors.add(pp); + if (pp instanceof MergedBeanDefinitionPostProcessor) { + internalPostProcessors.add(pp); + } + } + // 注册无序的 BeanPostProcessor + registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); + + // Finally, re-register all internal BeanPostProcessors. + sortPostProcessors(internalPostProcessors, beanFactory); + // 注册 MergedBeanDefinitionPostProcessor + 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). + // 添加 ApplicationListenerDetector + beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); + } + + +``` + + + +- 测试用Bean + +```java +public class DemoInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { + @Override + public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException { + System.out.println("init bean beanClass = " + beanClass.getSimpleName() + " beanName = " + beanName); + return null; + } +} +``` + + + +- 按照笔者的注释,可以知道`DemoInstantiationAwareBeanPostProcessor` 这个类是一个无序Bean + +  + + + + + +- 注册方法信息截图 + + + + + + + +### 使用阶段(调用阶段) + +在`org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])`中有如下代码 + +```JAVA + Object bean = resolveBeforeInstantiation(beanName, mbdToUse); +``` + +- `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation` + +```JAVA +@Nullable + protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { + Object bean = null; + if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { + // Make sure bean class is actually resolved at this point. + if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { + Class> targetType = determineTargetType(beanName, mbd); + if (targetType != null) { + /** + * 主要实现{@link org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(java.lang.Class, java.lang.String)} + */ + bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); + if (bean != null) { + bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); + } + } + } + mbd.beforeInstantiationResolved = (bean != null); + } + return bean; + } +``` + +- `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation` + +```JAVA + @Nullable + protected Object applyBeanPostProcessorsBeforeInstantiation(Class> beanClass, String beanName) { + for (BeanPostProcessor bp : getBeanPostProcessors()) { + if (bp instanceof InstantiationAwareBeanPostProcessor) { + InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; + // 调用自定义实现 + Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); + if (result != null) { + return result; + } + } + } + return null; + } + +``` + +这个地方已经可以看到`InstantiationAwareBeanPostProcessor`出现了,并且调用了方法`postProcessBeforeInstantiation`,此处就可以调用我们的自定义方法了 + + \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-DefaultSingletonBeanRegistry.md b/docs/Spring/clazz/Spring-DefaultSingletonBeanRegistry.md new file mode 100644 index 0000000..ccd1231 --- /dev/null +++ b/docs/Spring/clazz/Spring-DefaultSingletonBeanRegistry.md @@ -0,0 +1,278 @@ +# DefaultSingletonBeanRegistry +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) +- 源码路径: `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry` +- 官方提供的测试类: `org.springframework.beans.factory.support.DefaultSingletonBeanRegistryTests` + +类图 + +## 注册方法解析 +- 从名字可以看出这是一个单例对象的注册类 +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.registerSingleton` + + + +- 测试用例出发 + + ```java + @Test + public void testSingletons() { + DefaultSingletonBeanRegistry beanRegistry = new DefaultSingletonBeanRegistry(); + + TestBean tb = new TestBean(); + beanRegistry.registerSingleton("tb", tb); + assertSame(tb, beanRegistry.getSingleton("tb")); + + TestBean tb2 = (TestBean) beanRegistry.getSingleton("tb2", new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return new TestBean(); + } + }); + assertSame(tb2, beanRegistry.getSingleton("tb2")); + + assertSame(tb, beanRegistry.getSingleton("tb")); + assertSame(tb2, beanRegistry.getSingleton("tb2")); + assertEquals(2, beanRegistry.getSingletonCount()); + String[] names = beanRegistry.getSingletonNames(); + assertEquals(2, names.length); + assertEquals("tb", names[0]); + assertEquals("tb2", names[1]); + + beanRegistry.destroySingletons(); + assertEquals(0, beanRegistry.getSingletonCount()); + assertEquals(0, beanRegistry.getSingletonNames().length); + } + + ``` + + + +- 第一个关注的方法`org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#registerSingleton` 注册单例对象 + +```java + /** + * 注册一个单例对象 + * + * @param beanName the name of the bean + * @param singletonObject the existing singleton object + * @throws IllegalStateException + */ + @Override + public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { + Assert.notNull(beanName, "Bean name must not be null"); + Assert.notNull(singletonObject, "Singleton object must not be null"); + synchronized (this.singletonObjects) { + // 通过beanName获取单例对象 + Object oldObject = this.singletonObjects.get(beanName); + // 不为空异常 + if (oldObject != null) { + throw new IllegalStateException("Could not register object [" + singletonObject + + "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound"); + } + // 添加方法 + addSingleton(beanName, singletonObject); + } + } + +``` +```java + /** + * Add the given singleton object to the singleton cache of this factory. + * To be called for eager registration of singletons. + * + * 添加单例对象的操作方法 + * + * @param beanName the name of the bean + * @param singletonObject the singleton object + */ + protected void addSingleton(String beanName, Object singletonObject) { + synchronized (this.singletonObjects) { + this.singletonObjects.put(beanName, singletonObject); + this.singletonFactories.remove(beanName); + this.earlySingletonObjects.remove(beanName); + this.registeredSingletons.add(beanName); + } + } +``` +- 这些变量是什么 +```java + /** + * 单例对象的缓存: beanName -> Object + */ + private final Map singletonObjects = new ConcurrentHashMap<>(256); + + /** + * 单例工厂的缓存: beanName -> ObjectFactory。 + */ + private final Map> singletonFactories = new HashMap<>(16); + + /** + * 延迟加载的单例对象缓存: beanName -> Object + */ + private final Map earlySingletonObjects = new HashMap<>(16); + + /** + * 已经注册过的单例对象名称(beanName) + */ + private final Set registeredSingletons = new LinkedHashSet<>(256); + + /** + * 当前正在创建的单例对象名称(beanName) + */ + private final Set singletonsCurrentlyInCreation = + Collections.newSetFromMap(new ConcurrentHashMap<>(16)); + + private final Set inCreationCheckExclusions = + Collections.newSetFromMap(new ConcurrentHashMap<>(16)); + /** + * 摧毁单例对象 + */ + private final Map disposableBeans = new LinkedHashMap<>(); + private final Map> containedBeanMap = new ConcurrentHashMap<>(16); + /** + * bean 和beanName的关系 + */ + private final Map> dependentBeanMap = new ConcurrentHashMap<>(64); + /** + * bean 依赖关系 beanName -> 依赖关系 + */ + private final Map> dependenciesForBeanMap = new ConcurrentHashMap<>(64); + /** + * 异常列表 + */ + @Nullable + private Set suppressedExceptions; + /** + * 标记是否在 destroySingletons 上 + */ + private boolean singletonsCurrentlyInDestruction = false; + +``` + +- 注册方法至此结束 + +## 获取方法解析 +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(java.lang.String)` +```java + @Override + @Nullable + public Object getSingleton(String beanName) { + return getSingleton(beanName, true); + } +``` + +```java + @Nullable + protected Object getSingleton(String beanName, boolean allowEarlyReference) { + // 从列表中获取单例对象 + Object singletonObject = this.singletonObjects.get(beanName); + // 判断当前beanName是否存在 + if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { + synchronized (this.singletonObjects) { + // 从延迟加载中获取 + singletonObject = this.earlySingletonObjects.get(beanName); + if (singletonObject == null && allowEarlyReference) { + // 从singletonFactories获取ObjectFactory + ObjectFactory> singletonFactory = this.singletonFactories.get(beanName); + if (singletonFactory != null) { + // 获取对象 + singletonObject = singletonFactory.getObject(); + // 加入缓存 + this.earlySingletonObjects.put(beanName, singletonObject); + this.singletonFactories.remove(beanName); + } + } + } + } + return singletonObject; + } + +``` + +- 获取单例对象的本质就是从map中获取 ObjectFactory 进而执行 getObject() +`ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);` +- 测试方法 +```java + + TestBean tb2 = (TestBean) beanRegistry.getSingleton("tb2", new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return new TestBean(); + } + }); +``` + +- 获取单例对象的方式 + +```java +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; + } + } +``` + +不难发现最后都是通过`singletonObject = singletonFactory.getObject();`进行获取 + +这个地方的方法实际上就是测试类中的 + +```java +new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return new TestBean(); + } + } +``` + +通过`getObject`就可以获取当前对象 \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-OrderComparator.md b/docs/Spring/clazz/Spring-OrderComparator.md new file mode 100644 index 0000000..173f546 --- /dev/null +++ b/docs/Spring/clazz/Spring-OrderComparator.md @@ -0,0 +1,98 @@ +# Spring OrderComparator +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) + + +```java + private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) { + boolean p1 = (o1 instanceof PriorityOrdered); + boolean p2 = (o2 instanceof PriorityOrdered); + if (p1 && !p2) { + return -1; + } else if (p2 && !p1) { + return 1; + } + + int i1 = getOrder(o1, sourceProvider); + int i2 = getOrder(o2, sourceProvider); + // 对比两个Order值得大小返回 + return Integer.compare(i1, i2); + } + +``` + +```java + private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) { + Integer order = null; + if (obj != null && sourceProvider != null) { + // 获取Order + Object orderSource = sourceProvider.getOrderSource(obj); + if (orderSource != null) { + if (orderSource.getClass().isArray()) { + // 获取 OrderSourceProvider 的值 + Object[] sources = ObjectUtils.toObjectArray(orderSource); + for (Object source : sources) { + // 找 order 返回 + order = findOrder(source); + if (order != null) { + break; + } + } + } else { + // 寻找 order + order = findOrder(orderSource); + } + } + } + return (order != null ? order : getOrder(obj)); + } + +``` + +- 测试用例 +```java + @Test + public void compareWithSourceProviderArray() { + Comparator customComparator = this.comparator.withSourceProvider( + new TestSourceProvider(5L, new Object[]{new StubOrdered(10), new StubOrdered(-25)})); + assertEquals(-1, customComparator.compare(5L, new Object())); + } + +``` + + + + + +```java + @Nullable + protected Integer findOrder(Object obj) { + // 获取Ordered实现类 + return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null); + } + +``` + +```java + private static final class StubOrdered implements Ordered { + + private final int order; + + + public StubOrdered(int order) { + this.order = order; + } + + @Override + public int getOrder() { + return this.order; + } + } + +``` + + + + + +最终`Integer.compare(i1, i2)`比较返回 OK ! \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-scan.md b/docs/Spring/clazz/Spring-scan.md new file mode 100644 index 0000000..5e03fe9 --- /dev/null +++ b/docs/Spring/clazz/Spring-scan.md @@ -0,0 +1,534 @@ +# Spring scan +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) + +## 解析 +- Spring 注解形式使用有下面两种方式 + 1. 通过`AnnotationConfigApplicationContext`参数:扫描包 + 2. 通过xml配置`context:component-scan`属性`base-package` +```java + AnnotationConfigApplicationContext aac = + new AnnotationConfigApplicationContext("com.huifer.source.spring.ann"); +``` +```xml + + +``` + +- 目标明确开始找入口方法 +- `AnnotationConfigApplicationContext`直接点进去看就找到了 +```java +public AnnotationConfigApplicationContext(String... basePackages) { + this(); + // 扫描包 + scan(basePackages); + refresh(); + } +``` +- `context:component-scan`寻找方式:冒号`:`钱+NamespaceHandler 或者全文搜索`component-scan`,最终找到`org.springframework.context.config.ContextNamespaceHandler` +```java +public class ContextNamespaceHandler extends NamespaceHandlerSupport { + + @Override + public void init() { + registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); + registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); + registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); + registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); + registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser()); + registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); + registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser()); + registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser()); + } + +} +``` + +### org.springframework.context.annotation.ComponentScanBeanDefinitionParser + + + +- 实现`BeanDefinitionParser`直接看`parse`方法 +```java + @Override + @Nullable + public BeanDefinition parse(Element element, ParserContext parserContext) { + // 获取 base-package 属性值 + String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); + // 处理 ${} + basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); + // 分隔符`,;\t\n`切分 + String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, + ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); + + // Actually scan for bean definitions and register them. + // 扫描对象创建 + ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); + // 执行扫描方法 + Set beanDefinitions = scanner.doScan(basePackages); + // 注册组件,触发监听 + registerComponents(parserContext.getReaderContext(), beanDefinitions, element); + + return null; + } + +``` + +- 回过头看`AnnotationConfigApplicationContext` +### org.springframework.context.annotation.AnnotationConfigApplicationContext +```java +public AnnotationConfigApplicationContext(String... basePackages) { + this(); + // 扫描包 + scan(basePackages); + refresh(); + } +``` +```java + private final ClassPathBeanDefinitionScanner scanner; + + @Override + public void scan(String... basePackages) { + Assert.notEmpty(basePackages, "At least one base package must be specified"); + this.scanner.scan(basePackages); + } + +``` +- `org.springframework.context.annotation.ClassPathBeanDefinitionScanner.scan` +```java +public int scan(String... basePackages) { + + // 获取bean数量 + 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); + } +``` + +- 这个地方`doScan`似曾相识,他就是`org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse`中的`doScan`,下一步解析doScan + +### org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan + + + +```java + protected Set doScan(String... basePackages) { + Assert.notEmpty(basePackages, "At least one base package must be specified"); + Set beanDefinitions = new LinkedHashSet<>(); + for (String basePackage : basePackages) { + // 寻找组件 + Set candidates = findCandidateComponents(basePackage); + for (BeanDefinition candidate : candidates) { + // bean 作用域设置 + ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); + // 设置生命周期 + candidate.setScope(scopeMetadata.getScopeName()); + // 创建beanName + String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); + if (candidate instanceof AbstractBeanDefinition) { + // 设置默认属性 具体方法:org.springframework.beans.factory.support.AbstractBeanDefinition.applyDefaults + postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); + } + if (candidate instanceof AnnotatedBeanDefinition) { + // 读取Lazy,Primary 等注解 + AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); + } + // bean的重复检查 + if (checkCandidate(beanName, candidate)) { + // 创建 BeanDefinitionHolder + BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); + // 代理对象的处理 + definitionHolder = + AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); + // 放入list中,最后返回用 + beanDefinitions.add(definitionHolder); + // 注册bean + registerBeanDefinition(definitionHolder, this.registry); + } + } + } + return beanDefinitions; + } + +``` + + + +#### org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents + +```java + public Set findCandidateComponents(String basePackage) { + // 扫描 + if (this.componentsIndex != null && indexSupportsIncludeFilters()) { + return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); + } + else { + return scanCandidateComponents(basePackage); + } + } + +``` + + + +```java + /** + * 扫描当前包路径下的资源 + * @param basePackage + * @return + */ + private Set scanCandidateComponents(String basePackage) { + Set candidates = new LinkedHashSet<>(); + try { + // 字符串拼接出一个编译后的路径 classpath:// + // 这里替换了通配符 + String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + + resolveBasePackage(basePackage) + '/' + this.resourcePattern; + // 获取资源 + Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); + // 日志级别 + boolean traceEnabled = logger.isTraceEnabled(); + boolean debugEnabled = logger.isDebugEnabled(); + for (Resource resource : resources) { + if (traceEnabled) { + logger.trace("Scanning " + resource); + } + if (resource.isReadable()) { + try { + // 获取 MetadataReader + MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); + // 判断是否是 Component + if (isCandidateComponent(metadataReader)) { + ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); + sbd.setResource(resource); + sbd.setSource(resource); + if (isCandidateComponent(sbd)) { + if (debugEnabled) { + logger.debug("Identified candidate component class: " + resource); + } + candidates.add(sbd); + } + else { + if (debugEnabled) { + logger.debug("Ignored because not a concrete top-level class: " + resource); + } + } + } + else { + if (traceEnabled) { + logger.trace("Ignored because not matching any filter: " + resource); + } + } + } + catch (Throwable ex) { + throw new BeanDefinitionStoreException( + "Failed to read candidate component class: " + resource, ex); + } + } + else { + if (traceEnabled) { + logger.trace("Ignored because not readable: " + resource); + } + } + } + } + catch (IOException ex) { + throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); + } + return candidates; + } + +``` + + + +#### org.springframework.context.annotation.ScopeMetadataResolver#resolveScopeMetadata + + + +```java + /** + * 生命周期设置 + * + * @param definition the target bean definition + * @return + */ + @Override + public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) { + ScopeMetadata metadata = new ScopeMetadata(); + // 判断是否属于 AnnotatedBeanDefinition + if (definition instanceof AnnotatedBeanDefinition) { + AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition; + AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor( + annDef.getMetadata(), this.scopeAnnotationType); + if (attributes != null) { + // 获取 value 属性值并且设置 + metadata.setScopeName(attributes.getString("value")); + // 获取 proxyMode 属性值并且设置 + ScopedProxyMode proxyMode = attributes.getEnum("proxyMode"); + if (proxyMode == ScopedProxyMode.DEFAULT) { + proxyMode = this.defaultProxyMode; + } + metadata.setScopedProxyMode(proxyMode); + } + } + return metadata; + } + + +``` + +- `org.springframework.context.annotation.AnnotationScopeMetadataResolverTests#resolveScopeMetadataShouldReadScopedProxyModeFromAnnotation`测试用例 + +```java + @Test + public void resolveScopeMetadataShouldReadScopedProxyModeFromAnnotation() { + AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(AnnotatedWithScopedProxy.class); + ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(bd); + assertNotNull("resolveScopeMetadata(..) must *never* return null.", scopeMetadata); + assertEquals("request", scopeMetadata.getScopeName()); + assertEquals(TARGET_CLASS, scopeMetadata.getScopedProxyMode()); + } + +``` + + + +#### org.springframework.beans.factory.support.BeanNameGenerator#generateBeanName + +- 创建beanName `org.springframework.context.annotation.AnnotationBeanNameGenerator#generateBeanName` + + + +```java + @Override + public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { + if (definition instanceof AnnotatedBeanDefinition) { + // 如果存在bean(value="") value存在 + String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition); + if (StringUtils.hasText(beanName)) { + // Explicit bean name found. + return beanName; + } + } + // Fallback: generate a unique default bean name. + // 创建beanName + return buildDefaultBeanName(definition, registry); + } + +``` + +```java + @Nullable + protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) { + AnnotationMetadata amd = annotatedDef.getMetadata(); + Set types = amd.getAnnotationTypes(); + String beanName = null; + for (String type : types) { + AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type); + if (attributes != null && isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) { + // 获取注解的value 属性值 + Object value = attributes.get("value"); + if (value instanceof String) { + String strVal = (String) value; + // 判断是否存在值 + if (StringUtils.hasLength(strVal)) { + if (beanName != null && !strVal.equals(beanName)) { + throw new IllegalStateException("Stereotype annotations suggest inconsistent " + + "component names: '" + beanName + "' versus '" + strVal + "'"); + } + // beanName = value属性值 + beanName = strVal; + } + } + } + } + return beanName; + } + +``` + +```java +@Service(value = "dhc") +public class DemoService { + +} +``` + + + + + + + +- `org.springframework.context.annotation.AnnotationBeanNameGenerator#buildDefaultBeanName(org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.support.BeanDefinitionRegistry)` + - `org.springframework.context.annotation.AnnotationBeanNameGenerator#buildDefaultBeanName(org.springframework.beans.factory.config.BeanDefinition)` + + + +```JAVA + protected String buildDefaultBeanName(BeanDefinition definition) { + // 获取bean class name + String beanClassName = definition.getBeanClassName(); + Assert.state(beanClassName != null, "No bean class name set"); + // 获取短类名, + String shortClassName = ClassUtils.getShortName(beanClassName); + // 第一个字母小写 + return Introspector.decapitalize(shortClassName); + } + +``` + +```JAVA +@Configuration +public class BeanConfig { + @Scope(value =ConfigurableBeanFactory.SCOPE_PROTOTYPE) + @Bean(value = "hc") + public Ubean f() { + return new Ubean(); + } +} + +``` + + + + + + + +#### org.springframework.context.annotation.ClassPathBeanDefinitionScanner#postProcessBeanDefinition + +- 这个方法没什么难点,直接是set方法 + +```java + protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) { + beanDefinition.applyDefaults(this.beanDefinitionDefaults); + if (this.autowireCandidatePatterns != null) { + beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName)); + } + } + +``` + +```java + public void applyDefaults(BeanDefinitionDefaults defaults) { + setLazyInit(defaults.isLazyInit()); + setAutowireMode(defaults.getAutowireMode()); + setDependencyCheck(defaults.getDependencyCheck()); + setInitMethodName(defaults.getInitMethodName()); + setEnforceInitMethod(false); + setDestroyMethodName(defaults.getDestroyMethodName()); + setEnforceDestroyMethod(false); + } + +``` + +#### org.springframework.context.annotation.AnnotationConfigUtils#processCommonDefinitionAnnotations(org.springframework.beans.factory.annotation.AnnotatedBeanDefinition) + +```java + public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) { + processCommonDefinitionAnnotations(abd, abd.getMetadata()); + } + +``` + +```java +static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) { + // 获取 lazy 注解 + AnnotationAttributes lazy = attributesFor(metadata, Lazy.class); + if (lazy != null) { + abd.setLazyInit(lazy.getBoolean("value")); + } else if (abd.getMetadata() != metadata) { + lazy = attributesFor(abd.getMetadata(), Lazy.class); + if (lazy != null) { + abd.setLazyInit(lazy.getBoolean("value")); + } + } + + if (metadata.isAnnotated(Primary.class.getName())) { + abd.setPrimary(true); + } + AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class); + if (dependsOn != null) { + abd.setDependsOn(dependsOn.getStringArray("value")); + } + + AnnotationAttributes role = attributesFor(metadata, Role.class); + if (role != null) { + abd.setRole(role.getNumber("value").intValue()); + } + AnnotationAttributes description = attributesFor(metadata, Description.class); + if (description != null) { + abd.setDescription(description.getString("value")); + } + } +``` + + + +- 方法思路: + 1. 获取注解的属性值 + 2. 设置注解属性 + + + + + +#### org.springframework.context.annotation.ClassPathBeanDefinitionScanner#checkCandidate + +- 重复检查 + +```java + protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException { + // 判断当前 beanName 是否在注册表中 + if (!this.registry.containsBeanDefinition(beanName)) { + return true; + } + // 从注册表中获取 + BeanDefinition existingDef = this.registry.getBeanDefinition(beanName); + // 当前的bean + BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition(); + if (originatingDef != null) { + existingDef = originatingDef; + } + if (isCompatible(beanDefinition, existingDef)) { + return false; + } + throw new ConflictingBeanDefinitionException("Annotation-specified bean name '" + beanName + + "' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, " + + "non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]"); + } + +``` + + + + + +#### org.springframework.context.annotation.AnnotationConfigUtils#applyScopedProxyMode + + + +```JAVA + static BeanDefinitionHolder applyScopedProxyMode( + ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) { + + ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode(); + if (scopedProxyMode.equals(ScopedProxyMode.NO)) { + return definition; + } + boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS); + // 创建代理对象 + return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass); + } + +``` + diff --git a/docs/Spring/clazz/Spring-自定义标签解析.md b/docs/Spring/clazz/Spring-自定义标签解析.md new file mode 100644 index 0000000..8a700f8 --- /dev/null +++ b/docs/Spring/clazz/Spring-自定义标签解析.md @@ -0,0 +1,658 @@ +# Spring 自定义标签解析 +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) +- 与自定义标签解析相关的类 + 1. `org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser` + 2. `org.springframework.beans.factory.xml.NamespaceHandlerSupport` + +- 开始源码之前先搭建一个环境 + + +## 环境搭建 +- 创建对象 +```java +public class UserXtd { + private String userName; + private String emailAddress; + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getEmailAddress() { + return emailAddress; + } + + public void setEmailAddress(String emailAddress) { + this.emailAddress = emailAddress; + } +} +``` +- 创建 xsd 文件 +```xml + + + + + + + + + + + +``` +- 创建 namespaceHandler +```java +public class UserNamespaceHandler extends NamespaceHandlerSupport { + @Override + public void init() { + registerBeanDefinitionParser("myUser", new UserBeanDefinitionParser()); + } +} +``` +- 创建 beanDefinitionParser +```java +public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { + /** + * 标签对应class + * @param element the {@code Element} that is being parsed + * @return + */ + @Override + protected Class> getBeanClass(Element element) { + return UserXtd.class; + } + + + @Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + // 获取 userName 标签属性值 + String name = element.getAttribute("userName"); + // 获取 emailAddress 标签属性值 + String address = element.getAttribute("emailAddress"); + + if (StringUtils.hasText(name)) { + builder.addPropertyValue("userName", name); + } + if (StringUtils.hasText(address)) { + builder.addPropertyValue("emailAddress", address); + } + } +} + +``` +- 创建 resource/META-INF/spring.handlers +```text +http\://www.huifer.com/schema/user=com.huifer.source.spring.parser.UserNamespaceHandler +``` +- 创建 resource/META-INF/spring.schemas +```text +http\://www.huifer.com/schema/user.xsd=META-INF/spring-test.xsd +``` +- 创建测试用例xml +```xml + + + + + + +``` +- 创建 Java 运行方法 +```java +/** + * 自定义标签测试用例 + */ +public class XSDDemo { + public static void main(String[] args) { + ApplicationContext applicationContext = new ClassPathXmlApplicationContext("XTD-xml.xml"); + UserXtd user = (UserXtd) applicationContext.getBean("testUserBean"); + System.out.println(user.getEmailAddress()); + } +} +``` +- 这里我们希望输出结果是`huifer97@163.com`,运行后结果也确实是`huifer97@163.com` + +## 解析 DefaultNamespaceHandlerResolver +- 入口方法`org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions` +```java + 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 { + // 非spring 默认标签解析 + delegate.parseCustomElement(ele); + } + } + } + } + else { + delegate.parseCustomElement(root); + } + } + +``` +- 调用链路 +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(org.w3c.dom.Element)` + - `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)` + +```java + /** + * Parse a custom element (outside of the default namespace). + * + * 自定义标签解析 + * + * @param ele the element to parse + * @param containingBd the containing bean definition (if any) + * @return the resulting bean definition + */ + @Nullable + 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)); + } + +``` + + + +- `http://www.huifer.com/schema/user`和我们定义的xsd文件中的url相同,如何找到对应的NamespaceHandler,在`META-INF/spring.handlers`中有定义, + + `http\://www.huifer.com/schema/user=com.huifer.source.spring.parser.UserNamespaceHandler` + + `NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);`这行代码就是获取`spring.handlers`中的定义 + +- 处理方法`org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve` + + + +```java + /** + * Locate the {@link NamespaceHandler} for the supplied namespace URI + * from the configured mappings. + * + * 根据 namespaceUri 获取对应的 {@link NamespaceHandler} + * @param namespaceUri the relevant namespace URI + * @return the located {@link NamespaceHandler}, or {@code null} if none found + */ + @Override + @Nullable + public NamespaceHandler resolve(String namespaceUri) { + // 获取handlerMapping + Map handlerMappings = getHandlerMappings(); + // 从 handlerMapping 中获取类名 + 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); + // 调用init()方法,自定义类中实现 + namespaceHandler.init(); + // 放入缓存 + handlerMappings.put(namespaceUri, namespaceHandler); + // 返回自定义的 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); + } + } + } + +``` + + + +- `org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#getHandlerMappings`跟踪这个方法 + +```JAVA + /** + * Load the specified NamespaceHandler mappings lazily. + * + * 获取handlerMappings + */ + private Map getHandlerMappings() { + Map handlerMappings = this.handlerMappings; + } +``` + + + + + +- 这里直接存在数据了,他是从什么时候加载的? + +- `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions` + + 这个方法在注册bean定义的时候调用 + + ```java + public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { + BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); + int countBefore = getRegistry().getBeanDefinitionCount(); + // 注册方法 + // createReaderContext 初始化HandlerMapping + documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); + return getRegistry().getBeanDefinitionCount() - countBefore; + } + + ``` + +- 继续跟踪`createReaderContext` + + ```java + org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createReaderContext + ``` + + ```java + public XmlReaderContext createReaderContext(Resource resource) { + return new XmlReaderContext(resource, this.problemReporter, this.eventListener, + this.sourceExtractor, this, getNamespaceHandlerResolver()); + } + + ``` + +- 继续跟踪`getNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#getNamespaceHandlerResolver` + + ```java + public NamespaceHandlerResolver getNamespaceHandlerResolver() { + if (this.namespaceHandlerResolver == null) { + this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver(); + } + return this.namespaceHandlerResolver; + } + + ``` + +- 继续跟踪`createDefaultNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createDefaultNamespaceHandlerResolver` + + ```java + protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() { + ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader()); + return new DefaultNamespaceHandlerResolver(cl); + } + ``` + + + +- 继续跟踪`DefaultNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver` + + ```java + public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) { + this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); + } + + ``` + + 他回到了我们之前疑问的地方 `handlerMappings` 如何出现的 + + 断点 + +  + + ```JAVA + public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) { + this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); + } + ``` + + `public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";` + +  + + 此时还是空 + + 走完 + +  + + ```java + @Override + public String toString() { + return "NamespaceHandlerResolver using mappings " + getHandlerMappings(); + } + + ``` + + + +```JAVA + /** + * Load the specified NamespaceHandler mappings lazily. + * + * 获取handlerMappings + */ + private Map getHandlerMappings() { + Map handlerMappings = this.handlerMappings; + // 缓存不存在 + if (handlerMappings == null) { + synchronized (this) { + handlerMappings = this.handlerMappings; + if (handlerMappings == null) { + if (logger.isTraceEnabled()) { + logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]"); + } + try { + // 将本地文件读出 + Properties mappings = + PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader); + if (logger.isTraceEnabled()) { + logger.trace("Loaded NamespaceHandler mappings: " + mappings); + } + handlerMappings = new ConcurrentHashMap<>(mappings.size()); + // 转换成map结构 + CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings); + this.handlerMappings = handlerMappings; + } + catch (IOException ex) { + throw new IllegalStateException( + "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex); + } + } + } + } + return handlerMappings; + } + +``` + + + + + + + + + +## org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#resolve + +```java + @Override + @Nullable + public NamespaceHandler resolve(String namespaceUri) { + // 获取handlerMapping + Map handlerMappings = getHandlerMappings(); + // 从 handlerMapping 中获取类名 + 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); + // 调用init()方法,自定义类中实现 + namespaceHandler.init(); + // 放入缓存 + handlerMappings.put(namespaceUri, namespaceHandler); + // 返回自定义的 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); + } + } + } + +``` + +执行`init`方法 + +```java +public class UserNamespaceHandler extends NamespaceHandlerSupport { + @Override + public void init() { + registerBeanDefinitionParser("myUser", new UserBeanDefinitionParser()); + } +} +``` + +```java + /** + * Subclasses can call this to register the supplied {@link BeanDefinitionParser} to + * handle the specified element. The element name is the local (non-namespace qualified) + * name. + * + * 将标签名称,标签解析类放入 + */ + protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) { + this.parsers.put(elementName, parser); + } + +``` + + + +- 方法走完,回到开始的方法 + + ```java + /** + * Parse a custom element (outside of the default namespace). + * + * 自定义标签解析 + * + * @param ele the element to parse + * @param containingBd the containing bean definition (if any) + * @return the resulting bean definition + */ + @Nullable + public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { + // 自定义标签解析 + String namespaceUri = getNamespaceURI(ele); + if (namespaceUri == null) { + return null; + } + // 根据命名空间获取处理类 + // org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve + 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)); + } + + ``` + + + + + + + + + +## org.springframework.beans.factory.xml.NamespaceHandler#parse + +- `org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse` + + ```java + @Override + @Nullable + public BeanDefinition parse(Element element, ParserContext parserContext) { + BeanDefinitionParser parser = findParserForElement(element, parserContext); + return (parser != null ? parser.parse(element, parserContext) : null); + } + + ``` + +### org.springframework.beans.factory.xml.NamespaceHandlerSupport#findParserForElement + +```java + @Nullable + private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { + // 获取标签名称 + String localName = parserContext.getDelegate().getLocalName(element); + // 在map中获取对应的标签解析类 + BeanDefinitionParser parser = this.parsers.get(localName); + // 空报错 + if (parser == null) { + parserContext.getReaderContext().fatal( + "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); + } + // 不为空返回 + return parser; + } + +``` + + + +### org.springframework.beans.factory.xml.BeanDefinitionParser#parse + +- `org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parse` + +```java + public final BeanDefinition parse(Element element, ParserContext parserContext) { + /** + * {@link AbstractSingleBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)} + */ + AbstractBeanDefinition definition = parseInternal(element, parserContext); + + + } +``` + +### org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#parseInternal + +```java +@Override + protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); + String parentName = getParentName(element); + if (parentName != null) { + builder.getRawBeanDefinition().setParentName(parentName); + } + // 调用自己实现的方法 com.huifer.source.spring.parser.UserBeanDefinitionParser.getBeanClass + Class> beanClass = getBeanClass(element); + if (beanClass != null) { + builder.getRawBeanDefinition().setBeanClass(beanClass); + } + else { + // getBeanClassName 同样也是可以在自定义的解析类中实现 + 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. + // 设置scope + builder.setScope(containingBd.getScope()); + } + if (parserContext.isDefaultLazyInit()) { + // Default-lazy-init applies to custom bean definitions as well. + // 设置 lazy-init + builder.setLazyInit(true); + } + + // 执行解析方法,在自定义解析类中存在com.huifer.source.spring.parser.UserBeanDefinitionParser.doParse + doParse(element, parserContext, builder); + return builder.getBeanDefinition(); + } +``` + + + + + +执行`com.huifer.source.spring.parser.UserBeanDefinitionParser#doParse` + +```JAVA +@Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + // 获取 userName 标签属性值 + String name = element.getAttribute("userName"); + // 获取 emailAddress 标签属性值 + String address = element.getAttribute("emailAddress"); + + if (StringUtils.hasText(name)) { + builder.addPropertyValue("userName", name); + } + if (StringUtils.hasText(address)) { + builder.addPropertyValue("emailAddress", address); + } + } +``` + + + + + diff --git a/images/spring/image-20200109084131415.png b/images/spring/image-20200109084131415.png new file mode 100644 index 0000000..6d99aa1 Binary files /dev/null and b/images/spring/image-20200109084131415.png differ diff --git a/images/spring/image-20200109085606240.png b/images/spring/image-20200109085606240.png new file mode 100644 index 0000000..61883bf Binary files /dev/null and b/images/spring/image-20200109085606240.png differ diff --git a/images/spring/image-20200109090456547.png b/images/spring/image-20200109090456547.png new file mode 100644 index 0000000..19e745c Binary files /dev/null and b/images/spring/image-20200109090456547.png differ diff --git a/images/spring/image-20200109090655157.png b/images/spring/image-20200109090655157.png new file mode 100644 index 0000000..97c431c Binary files /dev/null and b/images/spring/image-20200109090655157.png differ diff --git a/images/spring/image-20200109091216505.png b/images/spring/image-20200109091216505.png new file mode 100644 index 0000000..cbc2d48 Binary files /dev/null and b/images/spring/image-20200109091216505.png differ diff --git a/images/spring/image-20200109092801572.png b/images/spring/image-20200109092801572.png new file mode 100644 index 0000000..043a9ca Binary files /dev/null and b/images/spring/image-20200109092801572.png differ diff --git a/images/spring/image-20200109093242494.png b/images/spring/image-20200109093242494.png new file mode 100644 index 0000000..8d8077f Binary files /dev/null and b/images/spring/image-20200109093242494.png differ diff --git a/images/spring/image-20200109094032421.png b/images/spring/image-20200109094032421.png new file mode 100644 index 0000000..a8dcfb1 Binary files /dev/null and b/images/spring/image-20200109094032421.png differ diff --git a/images/spring/image-20200109094649217.png b/images/spring/image-20200109094649217.png new file mode 100644 index 0000000..2c2b1f2 Binary files /dev/null and b/images/spring/image-20200109094649217.png differ diff --git a/images/spring/image-20200109094654409.png b/images/spring/image-20200109094654409.png new file mode 100644 index 0000000..2c2b1f2 Binary files /dev/null and b/images/spring/image-20200109094654409.png differ diff --git a/images/spring/image-20200109150841916.png b/images/spring/image-20200109150841916.png new file mode 100644 index 0000000..c85d445 Binary files /dev/null and b/images/spring/image-20200109150841916.png differ diff --git a/images/spring/image-20200110093044672.png b/images/spring/image-20200110093044672.png new file mode 100644 index 0000000..514b59c Binary files /dev/null and b/images/spring/image-20200110093044672.png differ diff --git a/images/spring/image-20200115083744268.png b/images/spring/image-20200115083744268.png new file mode 100644 index 0000000..8a465cd Binary files /dev/null and b/images/spring/image-20200115083744268.png differ diff --git a/images/spring/image-20200115084031725.png b/images/spring/image-20200115084031725.png new file mode 100644 index 0000000..6742458 Binary files /dev/null and b/images/spring/image-20200115084031725.png differ diff --git a/images/spring/image-20200115093602651.png b/images/spring/image-20200115093602651.png new file mode 100644 index 0000000..fa04a3c Binary files /dev/null and b/images/spring/image-20200115093602651.png differ diff --git a/images/spring/image-20200115105941265.png b/images/spring/image-20200115105941265.png new file mode 100644 index 0000000..88c456b Binary files /dev/null and b/images/spring/image-20200115105941265.png differ diff --git a/images/spring/image-20200115141708702.png b/images/spring/image-20200115141708702.png new file mode 100644 index 0000000..2c1ada0 Binary files /dev/null and b/images/spring/image-20200115141708702.png differ diff --git a/images/spring/image-20200115143315633.png b/images/spring/image-20200115143315633.png new file mode 100644 index 0000000..6edee36 Binary files /dev/null and b/images/spring/image-20200115143315633.png differ diff --git a/images/spring/image-20200115143456554.png b/images/spring/image-20200115143456554.png new file mode 100644 index 0000000..d19ba94 Binary files /dev/null and b/images/spring/image-20200115143456554.png differ diff --git a/images/spring/image-20200116085344737.png b/images/spring/image-20200116085344737.png new file mode 100644 index 0000000..6f39a30 Binary files /dev/null and b/images/spring/image-20200116085344737.png differ diff --git a/images/spring/image-20200116085423073.png b/images/spring/image-20200116085423073.png new file mode 100644 index 0000000..c40cad2 Binary files /dev/null and b/images/spring/image-20200116085423073.png differ diff --git a/images/spring/image-20200116085726577.png b/images/spring/image-20200116085726577.png new file mode 100644 index 0000000..31a3481 Binary files /dev/null and b/images/spring/image-20200116085726577.png differ diff --git a/images/spring/image-20200116085737632.png b/images/spring/image-20200116085737632.png new file mode 100644 index 0000000..ae8f4cb Binary files /dev/null and b/images/spring/image-20200116085737632.png differ diff --git a/images/spring/image-20200116085927359.png b/images/spring/image-20200116085927359.png new file mode 100644 index 0000000..7a02538 Binary files /dev/null and b/images/spring/image-20200116085927359.png differ diff --git a/images/spring/image-20200116092259944.png b/images/spring/image-20200116092259944.png new file mode 100644 index 0000000..0d20a5a Binary files /dev/null and b/images/spring/image-20200116092259944.png differ diff --git a/images/spring/image-20200116141838601.png b/images/spring/image-20200116141838601.png new file mode 100644 index 0000000..e4ee61b Binary files /dev/null and b/images/spring/image-20200116141838601.png differ diff --git a/images/spring/image-20200116141932486.png b/images/spring/image-20200116141932486.png new file mode 100644 index 0000000..8e06086 Binary files /dev/null and b/images/spring/image-20200116141932486.png differ diff --git a/images/spring/image-20200119085346675.png b/images/spring/image-20200119085346675.png new file mode 100644 index 0000000..2c23ebb Binary files /dev/null and b/images/spring/image-20200119085346675.png differ diff --git a/images/spring/image-20200119085655734.png b/images/spring/image-20200119085655734.png new file mode 100644 index 0000000..18bf79e Binary files /dev/null and b/images/spring/image-20200119085655734.png differ diff --git a/images/spring/image-20200119101017989.png b/images/spring/image-20200119101017989.png new file mode 100644 index 0000000..c8b3ad9 Binary files /dev/null and b/images/spring/image-20200119101017989.png differ diff --git a/images/spring/image-20200119101026726.png b/images/spring/image-20200119101026726.png new file mode 100644 index 0000000..14b6c3e Binary files /dev/null and b/images/spring/image-20200119101026726.png differ diff --git a/images/spring/image-20200119101107820.png b/images/spring/image-20200119101107820.png new file mode 100644 index 0000000..e2546cb Binary files /dev/null and b/images/spring/image-20200119101107820.png differ diff --git a/images/spring/image-20200119101516591.png b/images/spring/image-20200119101516591.png new file mode 100644 index 0000000..4236551 Binary files /dev/null and b/images/spring/image-20200119101516591.png differ
Correctly handles bridge {@link Method Methods} generated by the compiler. + *
Note that this method supports only a single level of meta-annotations. + * For support for arbitrary levels of meta-annotations, use + * {@link #findAnnotation(Method, Class)} instead. + * + * @param method the method to look for annotations on + * 被检查的函数 + * @param annotationType the annotation type to look for + * 需要检测的注解类型 + * @return the first matching annotation, or {@code null} if not found + * @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method) + * @see #getAnnotation(AnnotatedElement, Class) + */ + @Nullable + public static A getAnnotation(Method method, Class annotationType) { + // 函数 + Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method); + // 强制转换 + return getAnnotation((AnnotatedElement) resolvedMethod, annotationType); + } + +``` +- method + +  + +- annotationType + +  + +```java + @Nullable + public static A getAnnotation(AnnotatedElement annotatedElement, Class annotationType) { + try { + // 获取注解 + A annotation = annotatedElement.getAnnotation(annotationType); + if (annotation == null) { + for (Annotation metaAnn : annotatedElement.getAnnotations()) { + annotation = metaAnn.annotationType().getAnnotation(annotationType); + if (annotation != null) { + break; + } + } + } + return (annotation != null ? synthesizeAnnotation(annotation, annotatedElement) : null); + } catch (Throwable ex) { + handleIntrospectionFailure(annotatedElement, ex); + return null; + } + } + +``` +- `org.springframework.core.annotation.AnnotationUtils.synthesizeAnnotation(A, java.lang.reflect.AnnotatedElement)` +```java + public static A synthesizeAnnotation( + A annotation, @Nullable AnnotatedElement annotatedElement) { + + return synthesizeAnnotation(annotation, (Object) annotatedElement); + } + +``` +```java + /** + * 注解是否存在别名,没有直接返回 + * + * @param annotation 注解 + * @param annotatedElement 函数 + * @param + * @return + */ + @SuppressWarnings("unchecked") + static A synthesizeAnnotation(A annotation, @Nullable Object annotatedElement) { + if (annotation instanceof SynthesizedAnnotation || hasPlainJavaAnnotationsOnly(annotatedElement)) { + return annotation; + } + // 具体的注解 + Class extends Annotation> annotationType = annotation.annotationType(); + if (!isSynthesizable(annotationType)) { + return annotation; + } + + DefaultAnnotationAttributeExtractor attributeExtractor = + new DefaultAnnotationAttributeExtractor(annotation, annotatedElement); + InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor); + + // Can always expose Spring's SynthesizedAnnotation marker since we explicitly check for a + // synthesizable annotation before (which needs to declare @AliasFor from the same package) + Class>[] exposedInterfaces = new Class>[]{annotationType, SynthesizedAnnotation.class}; + return (A) Proxy.newProxyInstance(annotation.getClass().getClassLoader(), exposedInterfaces, handler); + } + +``` +-`org.springframework.core.annotation.AnnotationUtils.isSynthesizable` +```java + @SuppressWarnings("unchecked") + private static boolean isSynthesizable(Class extends Annotation> annotationType) { + if (hasPlainJavaAnnotationsOnly(annotationType)) { + return false; + } + // 从缓存中获取当前注解,不存在null + Boolean synthesizable = synthesizableCache.get(annotationType); + if (synthesizable != null) { + return synthesizable; + } + + synthesizable = Boolean.FALSE; + for (Method attribute : getAttributeMethods(annotationType)) { + if (!getAttributeAliasNames(attribute).isEmpty()) { + synthesizable = Boolean.TRUE; + break; + } + // 获取返回值类型 + Class> returnType = attribute.getReturnType(); + + // 根据返回值做不同处理 + if (Annotation[].class.isAssignableFrom(returnType)) { + Class extends Annotation> nestedAnnotationType = + (Class extends Annotation>) returnType.getComponentType(); + if (isSynthesizable(nestedAnnotationType)) { + synthesizable = Boolean.TRUE; + break; + } + } else if (Annotation.class.isAssignableFrom(returnType)) { + Class extends Annotation> nestedAnnotationType = (Class extends Annotation>) returnType; + if (isSynthesizable(nestedAnnotationType)) { + synthesizable = Boolean.TRUE; + break; + } + } + } + + synthesizableCache.put(annotationType, synthesizable); + return synthesizable; + } + +``` + +- `org.springframework.core.annotation.AnnotationUtils#getAttributeMethods` + +```java + static List getAttributeMethods(Class extends Annotation> annotationType) { + List methods = attributeMethodsCache.get(annotationType); + if (methods != null) { + return methods; + } + + methods = new ArrayList<>(); + // annotationType.getDeclaredMethods() 获取注解中的方法 + for (Method method : annotationType.getDeclaredMethods()) { + if (isAttributeMethod(method)) { + ReflectionUtils.makeAccessible(method); + methods.add(method); + } + } + + // 缓存 key:注解,value:函数列表 + attributeMethodsCache.put(annotationType, methods); + // 函数列表 + return methods; + } + +``` + +- `org.springframework.core.annotation.AnnotationUtils#isAttributeMethod` + +```java + /** + * Determine if the supplied {@code method} is an annotation attribute method. + * + * 做3个判断 + * + * 函数不为空(method != null) + * 参数列表是不是空(method.getParameterCount() == 0) + * 返回类型不是void(method.getReturnType() != void.class) + * + * + * @param method the method to check + * @return {@code true} if the method is an attribute method + * @since 4.2 + */ + static boolean isAttributeMethod(@Nullable Method method) { + return (method != null && method.getParameterCount() == 0 && method.getReturnType() != void.class); + } + +``` + +- `org.springframework.util.ReflectionUtils#makeAccessible(java.lang.reflect.Method)` + +```java +@SuppressWarnings("deprecation") // on JDK 9 + public static void makeAccessible(Method method) { + // 1. 方法修饰符是不是public + // 2. 注解是不是public + // 3. 是否重写 + if ((!Modifier.isPublic(method.getModifiers()) || + !Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible()) { + method.setAccessible(true); + } + } +``` + +处理结果 + + + + + +处理结果和Order定义相同 + +```java +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) +@Documented +public @interface Order { + + /** + * The order value. + * Default is {@link Ordered#LOWEST_PRECEDENCE}. + * + * 启动顺序,默认integer最大值 + * @see Ordered#getOrder() + */ + int value() default Ordered.LOWEST_PRECEDENCE; + +} +``` + + + +最终返回 + + + + + + + + + + + +## findAnnotation + +- `org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.Method, java.lang.Class)` + + ```java + @SuppressWarnings("unchecked") + @Nullable + public static A findAnnotation(Method method, @Nullable Class annotationType) { + Assert.notNull(method, "Method must not be null"); + if (annotationType == null) { + return null; + } + // 创建注解缓存,key:被扫描的函数,value:注解 + AnnotationCacheKey cacheKey = new AnnotationCacheKey(method, annotationType); + // 从findAnnotationCache获取缓存 + A result = (A) findAnnotationCache.get(cacheKey); + + if (result == null) { + Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method); + // 寻找注解 + result = findAnnotation((AnnotatedElement) resolvedMethod, annotationType); + if (result == null) { + result = searchOnInterfaces(method, annotationType, method.getDeclaringClass().getInterfaces()); + } + + Class> clazz = method.getDeclaringClass(); + while (result == null) { + clazz = clazz.getSuperclass(); + if (clazz == null || clazz == Object.class) { + break; + } + Set annotatedMethods = getAnnotatedMethodsInBaseType(clazz); + if (!annotatedMethods.isEmpty()) { + for (Method annotatedMethod : annotatedMethods) { + if (isOverride(method, annotatedMethod)) { + Method resolvedSuperMethod = BridgeMethodResolver.findBridgedMethod(annotatedMethod); + result = findAnnotation((AnnotatedElement) resolvedSuperMethod, annotationType); + if (result != null) { + break; + } + } + } + } + if (result == null) { + result = searchOnInterfaces(method, annotationType, clazz.getInterfaces()); + } + } + + if (result != null) { + // 处理注解 + result = synthesizeAnnotation(result, method); + // 添加缓存 + findAnnotationCache.put(cacheKey, result); + } + } + // 返回 + return result; + } + + ``` + + + +- `org.springframework.core.annotation.AnnotationUtils.AnnotationCacheKey` + + ```java + private static final class AnnotationCacheKey implements Comparable { + + /** + * 带有注解的函数或者类 + */ + private final AnnotatedElement element; + + /** + * 注解 + */ + private final Class extends Annotation> annotationType; + + public AnnotationCacheKey(AnnotatedElement element, Class extends Annotation> annotationType) { + this.element = element; + this.annotationType = annotationType; + } + + } + ``` + + + +- `org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.AnnotatedElement, java.lang.Class)` + + ```java + @Nullable + public static A findAnnotation( + AnnotatedElement annotatedElement, @Nullable Class annotationType) { + // 注解类型不为空 + if (annotationType == null) { + return null; + } + + // Do NOT store result in the findAnnotationCache since doing so could break + // findAnnotation(Class, Class) and findAnnotation(Method, Class). + // 寻找注解 + A ann = findAnnotation(annotatedElement, annotationType, new HashSet<>()); + return (ann != null ? synthesizeAnnotation(ann, annotatedElement) : null); + } + + ``` + + + + + +- `org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.AnnotatedElement, java.lang.Class, java.util.Set)` + + ```java + @Nullable + private static A findAnnotation( + AnnotatedElement annotatedElement, Class annotationType, Set visited) { + try { + // 直接获取注解 + A annotation = annotatedElement.getDeclaredAnnotation(annotationType); + if (annotation != null) { + return annotation; + } + // 多级注解 + for (Annotation declaredAnn : getDeclaredAnnotations(annotatedElement)) { + Class extends Annotation> declaredType = declaredAnn.annotationType(); + // 注解是否 由java.lang.annotation提供 + if (!isInJavaLangAnnotationPackage(declaredType) && visited.add(declaredAnn)) { + annotation = findAnnotation((AnnotatedElement) declaredType, annotationType, visited); + if (annotation != null) { + return annotation; + } + } + } + } catch (Throwable ex) { + handleIntrospectionFailure(annotatedElement, ex); + } + return null; + } + + ``` + + + + + +- `synthesizeAnnotation`方法就不再重复一遍了可以看上文 + + + + + + + +## getValue + +- 测试用例 + + ```java + @Test + public void getValueFromAnnotation() throws Exception { + Method method = SimpleFoo.class.getMethod("something", Object.class); + Order order = findAnnotation(method, Order.class); + + assertEquals(1, getValue(order, VALUE)); + assertEquals(1, getValue(order)); + } + ``` + + + +- `org.springframework.core.annotation.AnnotationUtils#getValue(java.lang.annotation.Annotation, java.lang.String)` + +```java + @Nullable + public static Object getValue(@Nullable Annotation annotation, @Nullable String attributeName) { + if (annotation == null || !StringUtils.hasText(attributeName)) { + return null; + } + try { + // 根据attributeName获取注解对应函数 + Method method = annotation.annotationType().getDeclaredMethod(attributeName); + ReflectionUtils.makeAccessible(method); + // 反射执行方法 + return method.invoke(annotation); + } catch (NoSuchMethodException ex) { + return null; + } catch (InvocationTargetException ex) { + rethrowAnnotationConfigurationException(ex.getTargetException()); + throw new IllegalStateException("Could not obtain value for annotation attribute '" + + attributeName + "' in " + annotation, ex); + } catch (Throwable ex) { + handleIntrospectionFailure(annotation.getClass(), ex); + return null; + } + } + +``` + + + +```java + @Nullable + public static Object getValue(Annotation annotation) { + return getValue(annotation, VALUE); + } + +``` + + + + + + + +## getDefaultValue + +- `org.springframework.core.annotation.AnnotationUtils#getDefaultValue(java.lang.annotation.Annotation)` + + + +```java + @Nullable + public static Object getDefaultValue(Annotation annotation) { + return getDefaultValue(annotation, VALUE); + } + +``` + +```java + @Nullable + public static Object getDefaultValue( + @Nullable Class extends Annotation> annotationType, @Nullable String attributeName) { + + if (annotationType == null || !StringUtils.hasText(attributeName)) { + return null; + } + try { + // 直接获取defaultValue + return annotationType.getDeclaredMethod(attributeName).getDefaultValue(); + } catch (Throwable ex) { + handleIntrospectionFailure(annotationType, ex); + return null; + } + } + +``` + diff --git a/docs/Spring/clazz/Spring-BeanFactoryPostProcessor.md b/docs/Spring/clazz/Spring-BeanFactoryPostProcessor.md new file mode 100644 index 0000000..81fe47a --- /dev/null +++ b/docs/Spring/clazz/Spring-BeanFactoryPostProcessor.md @@ -0,0 +1,447 @@ +# Spring BeanFactoryPostProcessor +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) +- 作用: 定制或修改`BeanDefinition`的属性 + + +## Demo +```java +public class ChangeAttrBeanPostProcessor implements BeanFactoryPostProcessor { + private Set attr; + + public ChangeAttrBeanPostProcessor() { + attr = new HashSet<>(); + } + + public Set getAttr() { + return attr; + } + + public void setAttr(Set attr) { + this.attr = attr; + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames(); + for (String beanName : beanDefinitionNames) { + BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); + + StringValueResolver stringValueResolver = new StringValueResolver() { + @Override + public String resolveStringValue(String strVal) { + if (attr.contains(strVal)) { + return "隐藏属性"; + } + else { + return strVal; + } + } + }; + BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(stringValueResolver); + visitor.visitBeanDefinition(beanDefinition); + } + } +} +``` + +```java +public class BeanFactoryPostProcessorSourceCode { + public static void main(String[] args) { + ApplicationContext context = new ClassPathXmlApplicationContext("BeanFactoryPostProcessor-demo.xml"); + Apple apple = context.getBean("apple", Apple.class); + System.out.println(apple); + } +} +``` + +```xml + + + + + + hc + + + + + + + + +``` + + + +## 初始化 + +- `org.springframework.context.support.AbstractApplicationContext#refresh` + + ```JAVA + invokeBeanFactoryPostProcessors(beanFactory); + ``` + + ```JAVA + 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())); + } + } + + ``` + +- `org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List)` + + ```JAVA + public static void invokeBeanFactoryPostProcessors( + ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) { + + // Invoke BeanDefinitionRegistryPostProcessors first, if any. + Set processedBeans = new HashSet<>(); + // 判断是否为BeanDefinitionRegistry类 + if (beanFactory instanceof BeanDefinitionRegistry) { + BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; + // 存放 BeanFactoryPostProcessor + List regularPostProcessors = new ArrayList<>(); + // 存放 BeanDefinitionRegistryPostProcessor + List registryProcessors = new ArrayList<>(); + + // 2.首先处理入参中的beanFactoryPostProcessors + for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { + // 判断是否是BeanDefinitionRegistryPostProcessor + if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { + BeanDefinitionRegistryPostProcessor registryProcessor = + (BeanDefinitionRegistryPostProcessor) postProcessor; + // + registryProcessor.postProcessBeanDefinitionRegistry(registry); + // BeanDefinitionRegistryPostProcessor 添加 + // 执行 postProcessBeanFactory + registryProcessors.add(registryProcessor); + } + // 这部分else 内容就是 BeanFactoryPostProcessor + else { + // BeanFactoryPostProcessor 添加 + 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 currentRegistryProcessors = new ArrayList<>(); + + // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. + /** + * 调用实现{@link PriorityOrdered}\{@link BeanDefinitionRegistryPostProcessor} + * todo: 2020年1月16日 解析方法 + * {@link DefaultListableBeanFactory#getBeanNamesForType(java.lang.Class, boolean, boolean)} + */ + 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); + } + } + // 排序Order + 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! + // 配置文件中的 BeanFactoryPostProcessor 处理 + String[] postProcessorNames = + beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); + + // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, + // Ordered, and the rest. + List priorityOrderedPostProcessors = new ArrayList<>(); + List orderedPostProcessorNames = new ArrayList<>(); + List 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 orderedPostProcessors = new ArrayList<>(); + for (String postProcessorName : orderedPostProcessorNames) { + orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); + } + sortPostProcessors(orderedPostProcessors, beanFactory); + invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); + + // Finally, invoke all other BeanFactoryPostProcessors. + // 配置文件中自定义的 BeanFactoryPostProcessor 注册 + List nonOrderedPostProcessors = new ArrayList<>(); + 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(); + } + ``` + + + + + + + + + + + +## InstantiationAwareBeanPostProcessor + +```java + protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { + PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this); + } +``` + + + +```java + public static void registerBeanPostProcessors( + ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { + // 获取 BeanPostProcessor + 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. + // BeanPostProcessor 通过PriorityOrdered保证顺序 + List priorityOrderedPostProcessors = new ArrayList<>(); + // MergedBeanDefinitionPostProcessor + List internalPostProcessors = new ArrayList<>(); + // 有序的 BeanPostProcessor + List orderedPostProcessorNames = new ArrayList<>(); + // 无序的 BeanPostProcessor + List nonOrderedPostProcessorNames = new ArrayList<>(); + for (String ppName : postProcessorNames) { + if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { + BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); + priorityOrderedPostProcessors.add(pp); + // 类型判断放入相应的list + 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. + /** + * 有{@link org.springframework.core.annotation.Order} 相关操作 + */ + sortPostProcessors(priorityOrderedPostProcessors, beanFactory); + // 注册 BeanPostProcessor 和 PriorityOrdered 实现 + registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); + + // Next, register the BeanPostProcessors that implement Ordered. + List orderedPostProcessors = new ArrayList<>(); + for (String ppName : orderedPostProcessorNames) { + BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); + orderedPostProcessors.add(pp); + if (pp instanceof MergedBeanDefinitionPostProcessor) { + internalPostProcessors.add(pp); + } + } + sortPostProcessors(orderedPostProcessors, beanFactory); + // 注册 实现Order 和 BeanPostProcessor + registerBeanPostProcessors(beanFactory, orderedPostProcessors); + + // Now, register all regular BeanPostProcessors. + List nonOrderedPostProcessors = new ArrayList<>(); + for (String ppName : nonOrderedPostProcessorNames) { + BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); + nonOrderedPostProcessors.add(pp); + if (pp instanceof MergedBeanDefinitionPostProcessor) { + internalPostProcessors.add(pp); + } + } + // 注册无序的 BeanPostProcessor + registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); + + // Finally, re-register all internal BeanPostProcessors. + sortPostProcessors(internalPostProcessors, beanFactory); + // 注册 MergedBeanDefinitionPostProcessor + 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). + // 添加 ApplicationListenerDetector + beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); + } + + +``` + + + +- 测试用Bean + +```java +public class DemoInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { + @Override + public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException { + System.out.println("init bean beanClass = " + beanClass.getSimpleName() + " beanName = " + beanName); + return null; + } +} +``` + + + +- 按照笔者的注释,可以知道`DemoInstantiationAwareBeanPostProcessor` 这个类是一个无序Bean + +  + + + + + +- 注册方法信息截图 + + + + + + + +### 使用阶段(调用阶段) + +在`org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])`中有如下代码 + +```JAVA + Object bean = resolveBeforeInstantiation(beanName, mbdToUse); +``` + +- `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation` + +```JAVA +@Nullable + protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { + Object bean = null; + if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { + // Make sure bean class is actually resolved at this point. + if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { + Class> targetType = determineTargetType(beanName, mbd); + if (targetType != null) { + /** + * 主要实现{@link org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(java.lang.Class, java.lang.String)} + */ + bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); + if (bean != null) { + bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); + } + } + } + mbd.beforeInstantiationResolved = (bean != null); + } + return bean; + } +``` + +- `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation` + +```JAVA + @Nullable + protected Object applyBeanPostProcessorsBeforeInstantiation(Class> beanClass, String beanName) { + for (BeanPostProcessor bp : getBeanPostProcessors()) { + if (bp instanceof InstantiationAwareBeanPostProcessor) { + InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; + // 调用自定义实现 + Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); + if (result != null) { + return result; + } + } + } + return null; + } + +``` + +这个地方已经可以看到`InstantiationAwareBeanPostProcessor`出现了,并且调用了方法`postProcessBeforeInstantiation`,此处就可以调用我们的自定义方法了 + + \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-DefaultSingletonBeanRegistry.md b/docs/Spring/clazz/Spring-DefaultSingletonBeanRegistry.md new file mode 100644 index 0000000..ccd1231 --- /dev/null +++ b/docs/Spring/clazz/Spring-DefaultSingletonBeanRegistry.md @@ -0,0 +1,278 @@ +# DefaultSingletonBeanRegistry +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) +- 源码路径: `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry` +- 官方提供的测试类: `org.springframework.beans.factory.support.DefaultSingletonBeanRegistryTests` + +类图 + +## 注册方法解析 +- 从名字可以看出这是一个单例对象的注册类 +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.registerSingleton` + + + +- 测试用例出发 + + ```java + @Test + public void testSingletons() { + DefaultSingletonBeanRegistry beanRegistry = new DefaultSingletonBeanRegistry(); + + TestBean tb = new TestBean(); + beanRegistry.registerSingleton("tb", tb); + assertSame(tb, beanRegistry.getSingleton("tb")); + + TestBean tb2 = (TestBean) beanRegistry.getSingleton("tb2", new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return new TestBean(); + } + }); + assertSame(tb2, beanRegistry.getSingleton("tb2")); + + assertSame(tb, beanRegistry.getSingleton("tb")); + assertSame(tb2, beanRegistry.getSingleton("tb2")); + assertEquals(2, beanRegistry.getSingletonCount()); + String[] names = beanRegistry.getSingletonNames(); + assertEquals(2, names.length); + assertEquals("tb", names[0]); + assertEquals("tb2", names[1]); + + beanRegistry.destroySingletons(); + assertEquals(0, beanRegistry.getSingletonCount()); + assertEquals(0, beanRegistry.getSingletonNames().length); + } + + ``` + + + +- 第一个关注的方法`org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#registerSingleton` 注册单例对象 + +```java + /** + * 注册一个单例对象 + * + * @param beanName the name of the bean + * @param singletonObject the existing singleton object + * @throws IllegalStateException + */ + @Override + public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { + Assert.notNull(beanName, "Bean name must not be null"); + Assert.notNull(singletonObject, "Singleton object must not be null"); + synchronized (this.singletonObjects) { + // 通过beanName获取单例对象 + Object oldObject = this.singletonObjects.get(beanName); + // 不为空异常 + if (oldObject != null) { + throw new IllegalStateException("Could not register object [" + singletonObject + + "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound"); + } + // 添加方法 + addSingleton(beanName, singletonObject); + } + } + +``` +```java + /** + * Add the given singleton object to the singleton cache of this factory. + * To be called for eager registration of singletons. + * + * 添加单例对象的操作方法 + * + * @param beanName the name of the bean + * @param singletonObject the singleton object + */ + protected void addSingleton(String beanName, Object singletonObject) { + synchronized (this.singletonObjects) { + this.singletonObjects.put(beanName, singletonObject); + this.singletonFactories.remove(beanName); + this.earlySingletonObjects.remove(beanName); + this.registeredSingletons.add(beanName); + } + } +``` +- 这些变量是什么 +```java + /** + * 单例对象的缓存: beanName -> Object + */ + private final Map singletonObjects = new ConcurrentHashMap<>(256); + + /** + * 单例工厂的缓存: beanName -> ObjectFactory。 + */ + private final Map> singletonFactories = new HashMap<>(16); + + /** + * 延迟加载的单例对象缓存: beanName -> Object + */ + private final Map earlySingletonObjects = new HashMap<>(16); + + /** + * 已经注册过的单例对象名称(beanName) + */ + private final Set registeredSingletons = new LinkedHashSet<>(256); + + /** + * 当前正在创建的单例对象名称(beanName) + */ + private final Set singletonsCurrentlyInCreation = + Collections.newSetFromMap(new ConcurrentHashMap<>(16)); + + private final Set inCreationCheckExclusions = + Collections.newSetFromMap(new ConcurrentHashMap<>(16)); + /** + * 摧毁单例对象 + */ + private final Map disposableBeans = new LinkedHashMap<>(); + private final Map> containedBeanMap = new ConcurrentHashMap<>(16); + /** + * bean 和beanName的关系 + */ + private final Map> dependentBeanMap = new ConcurrentHashMap<>(64); + /** + * bean 依赖关系 beanName -> 依赖关系 + */ + private final Map> dependenciesForBeanMap = new ConcurrentHashMap<>(64); + /** + * 异常列表 + */ + @Nullable + private Set suppressedExceptions; + /** + * 标记是否在 destroySingletons 上 + */ + private boolean singletonsCurrentlyInDestruction = false; + +``` + +- 注册方法至此结束 + +## 获取方法解析 +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(java.lang.String)` +```java + @Override + @Nullable + public Object getSingleton(String beanName) { + return getSingleton(beanName, true); + } +``` + +```java + @Nullable + protected Object getSingleton(String beanName, boolean allowEarlyReference) { + // 从列表中获取单例对象 + Object singletonObject = this.singletonObjects.get(beanName); + // 判断当前beanName是否存在 + if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { + synchronized (this.singletonObjects) { + // 从延迟加载中获取 + singletonObject = this.earlySingletonObjects.get(beanName); + if (singletonObject == null && allowEarlyReference) { + // 从singletonFactories获取ObjectFactory + ObjectFactory> singletonFactory = this.singletonFactories.get(beanName); + if (singletonFactory != null) { + // 获取对象 + singletonObject = singletonFactory.getObject(); + // 加入缓存 + this.earlySingletonObjects.put(beanName, singletonObject); + this.singletonFactories.remove(beanName); + } + } + } + } + return singletonObject; + } + +``` + +- 获取单例对象的本质就是从map中获取 ObjectFactory 进而执行 getObject() +`ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);` +- 测试方法 +```java + + TestBean tb2 = (TestBean) beanRegistry.getSingleton("tb2", new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return new TestBean(); + } + }); +``` + +- 获取单例对象的方式 + +```java +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; + } + } +``` + +不难发现最后都是通过`singletonObject = singletonFactory.getObject();`进行获取 + +这个地方的方法实际上就是测试类中的 + +```java +new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return new TestBean(); + } + } +``` + +通过`getObject`就可以获取当前对象 \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-OrderComparator.md b/docs/Spring/clazz/Spring-OrderComparator.md new file mode 100644 index 0000000..173f546 --- /dev/null +++ b/docs/Spring/clazz/Spring-OrderComparator.md @@ -0,0 +1,98 @@ +# Spring OrderComparator +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) + + +```java + private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) { + boolean p1 = (o1 instanceof PriorityOrdered); + boolean p2 = (o2 instanceof PriorityOrdered); + if (p1 && !p2) { + return -1; + } else if (p2 && !p1) { + return 1; + } + + int i1 = getOrder(o1, sourceProvider); + int i2 = getOrder(o2, sourceProvider); + // 对比两个Order值得大小返回 + return Integer.compare(i1, i2); + } + +``` + +```java + private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) { + Integer order = null; + if (obj != null && sourceProvider != null) { + // 获取Order + Object orderSource = sourceProvider.getOrderSource(obj); + if (orderSource != null) { + if (orderSource.getClass().isArray()) { + // 获取 OrderSourceProvider 的值 + Object[] sources = ObjectUtils.toObjectArray(orderSource); + for (Object source : sources) { + // 找 order 返回 + order = findOrder(source); + if (order != null) { + break; + } + } + } else { + // 寻找 order + order = findOrder(orderSource); + } + } + } + return (order != null ? order : getOrder(obj)); + } + +``` + +- 测试用例 +```java + @Test + public void compareWithSourceProviderArray() { + Comparator customComparator = this.comparator.withSourceProvider( + new TestSourceProvider(5L, new Object[]{new StubOrdered(10), new StubOrdered(-25)})); + assertEquals(-1, customComparator.compare(5L, new Object())); + } + +``` + + + + + +```java + @Nullable + protected Integer findOrder(Object obj) { + // 获取Ordered实现类 + return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null); + } + +``` + +```java + private static final class StubOrdered implements Ordered { + + private final int order; + + + public StubOrdered(int order) { + this.order = order; + } + + @Override + public int getOrder() { + return this.order; + } + } + +``` + + + + + +最终`Integer.compare(i1, i2)`比较返回 OK ! \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-scan.md b/docs/Spring/clazz/Spring-scan.md new file mode 100644 index 0000000..5e03fe9 --- /dev/null +++ b/docs/Spring/clazz/Spring-scan.md @@ -0,0 +1,534 @@ +# Spring scan +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) + +## 解析 +- Spring 注解形式使用有下面两种方式 + 1. 通过`AnnotationConfigApplicationContext`参数:扫描包 + 2. 通过xml配置`context:component-scan`属性`base-package` +```java + AnnotationConfigApplicationContext aac = + new AnnotationConfigApplicationContext("com.huifer.source.spring.ann"); +``` +```xml + + +``` + +- 目标明确开始找入口方法 +- `AnnotationConfigApplicationContext`直接点进去看就找到了 +```java +public AnnotationConfigApplicationContext(String... basePackages) { + this(); + // 扫描包 + scan(basePackages); + refresh(); + } +``` +- `context:component-scan`寻找方式:冒号`:`钱+NamespaceHandler 或者全文搜索`component-scan`,最终找到`org.springframework.context.config.ContextNamespaceHandler` +```java +public class ContextNamespaceHandler extends NamespaceHandlerSupport { + + @Override + public void init() { + registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); + registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); + registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); + registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); + registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser()); + registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); + registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser()); + registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser()); + } + +} +``` + +### org.springframework.context.annotation.ComponentScanBeanDefinitionParser + + + +- 实现`BeanDefinitionParser`直接看`parse`方法 +```java + @Override + @Nullable + public BeanDefinition parse(Element element, ParserContext parserContext) { + // 获取 base-package 属性值 + String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); + // 处理 ${} + basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); + // 分隔符`,;\t\n`切分 + String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, + ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); + + // Actually scan for bean definitions and register them. + // 扫描对象创建 + ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); + // 执行扫描方法 + Set beanDefinitions = scanner.doScan(basePackages); + // 注册组件,触发监听 + registerComponents(parserContext.getReaderContext(), beanDefinitions, element); + + return null; + } + +``` + +- 回过头看`AnnotationConfigApplicationContext` +### org.springframework.context.annotation.AnnotationConfigApplicationContext +```java +public AnnotationConfigApplicationContext(String... basePackages) { + this(); + // 扫描包 + scan(basePackages); + refresh(); + } +``` +```java + private final ClassPathBeanDefinitionScanner scanner; + + @Override + public void scan(String... basePackages) { + Assert.notEmpty(basePackages, "At least one base package must be specified"); + this.scanner.scan(basePackages); + } + +``` +- `org.springframework.context.annotation.ClassPathBeanDefinitionScanner.scan` +```java +public int scan(String... basePackages) { + + // 获取bean数量 + 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); + } +``` + +- 这个地方`doScan`似曾相识,他就是`org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse`中的`doScan`,下一步解析doScan + +### org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan + + + +```java + protected Set doScan(String... basePackages) { + Assert.notEmpty(basePackages, "At least one base package must be specified"); + Set beanDefinitions = new LinkedHashSet<>(); + for (String basePackage : basePackages) { + // 寻找组件 + Set candidates = findCandidateComponents(basePackage); + for (BeanDefinition candidate : candidates) { + // bean 作用域设置 + ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); + // 设置生命周期 + candidate.setScope(scopeMetadata.getScopeName()); + // 创建beanName + String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); + if (candidate instanceof AbstractBeanDefinition) { + // 设置默认属性 具体方法:org.springframework.beans.factory.support.AbstractBeanDefinition.applyDefaults + postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); + } + if (candidate instanceof AnnotatedBeanDefinition) { + // 读取Lazy,Primary 等注解 + AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); + } + // bean的重复检查 + if (checkCandidate(beanName, candidate)) { + // 创建 BeanDefinitionHolder + BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); + // 代理对象的处理 + definitionHolder = + AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); + // 放入list中,最后返回用 + beanDefinitions.add(definitionHolder); + // 注册bean + registerBeanDefinition(definitionHolder, this.registry); + } + } + } + return beanDefinitions; + } + +``` + + + +#### org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents + +```java + public Set findCandidateComponents(String basePackage) { + // 扫描 + if (this.componentsIndex != null && indexSupportsIncludeFilters()) { + return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); + } + else { + return scanCandidateComponents(basePackage); + } + } + +``` + + + +```java + /** + * 扫描当前包路径下的资源 + * @param basePackage + * @return + */ + private Set scanCandidateComponents(String basePackage) { + Set candidates = new LinkedHashSet<>(); + try { + // 字符串拼接出一个编译后的路径 classpath:// + // 这里替换了通配符 + String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + + resolveBasePackage(basePackage) + '/' + this.resourcePattern; + // 获取资源 + Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); + // 日志级别 + boolean traceEnabled = logger.isTraceEnabled(); + boolean debugEnabled = logger.isDebugEnabled(); + for (Resource resource : resources) { + if (traceEnabled) { + logger.trace("Scanning " + resource); + } + if (resource.isReadable()) { + try { + // 获取 MetadataReader + MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); + // 判断是否是 Component + if (isCandidateComponent(metadataReader)) { + ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); + sbd.setResource(resource); + sbd.setSource(resource); + if (isCandidateComponent(sbd)) { + if (debugEnabled) { + logger.debug("Identified candidate component class: " + resource); + } + candidates.add(sbd); + } + else { + if (debugEnabled) { + logger.debug("Ignored because not a concrete top-level class: " + resource); + } + } + } + else { + if (traceEnabled) { + logger.trace("Ignored because not matching any filter: " + resource); + } + } + } + catch (Throwable ex) { + throw new BeanDefinitionStoreException( + "Failed to read candidate component class: " + resource, ex); + } + } + else { + if (traceEnabled) { + logger.trace("Ignored because not readable: " + resource); + } + } + } + } + catch (IOException ex) { + throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); + } + return candidates; + } + +``` + + + +#### org.springframework.context.annotation.ScopeMetadataResolver#resolveScopeMetadata + + + +```java + /** + * 生命周期设置 + * + * @param definition the target bean definition + * @return + */ + @Override + public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) { + ScopeMetadata metadata = new ScopeMetadata(); + // 判断是否属于 AnnotatedBeanDefinition + if (definition instanceof AnnotatedBeanDefinition) { + AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition; + AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor( + annDef.getMetadata(), this.scopeAnnotationType); + if (attributes != null) { + // 获取 value 属性值并且设置 + metadata.setScopeName(attributes.getString("value")); + // 获取 proxyMode 属性值并且设置 + ScopedProxyMode proxyMode = attributes.getEnum("proxyMode"); + if (proxyMode == ScopedProxyMode.DEFAULT) { + proxyMode = this.defaultProxyMode; + } + metadata.setScopedProxyMode(proxyMode); + } + } + return metadata; + } + + +``` + +- `org.springframework.context.annotation.AnnotationScopeMetadataResolverTests#resolveScopeMetadataShouldReadScopedProxyModeFromAnnotation`测试用例 + +```java + @Test + public void resolveScopeMetadataShouldReadScopedProxyModeFromAnnotation() { + AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(AnnotatedWithScopedProxy.class); + ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(bd); + assertNotNull("resolveScopeMetadata(..) must *never* return null.", scopeMetadata); + assertEquals("request", scopeMetadata.getScopeName()); + assertEquals(TARGET_CLASS, scopeMetadata.getScopedProxyMode()); + } + +``` + + + +#### org.springframework.beans.factory.support.BeanNameGenerator#generateBeanName + +- 创建beanName `org.springframework.context.annotation.AnnotationBeanNameGenerator#generateBeanName` + + + +```java + @Override + public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { + if (definition instanceof AnnotatedBeanDefinition) { + // 如果存在bean(value="") value存在 + String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition); + if (StringUtils.hasText(beanName)) { + // Explicit bean name found. + return beanName; + } + } + // Fallback: generate a unique default bean name. + // 创建beanName + return buildDefaultBeanName(definition, registry); + } + +``` + +```java + @Nullable + protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) { + AnnotationMetadata amd = annotatedDef.getMetadata(); + Set types = amd.getAnnotationTypes(); + String beanName = null; + for (String type : types) { + AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type); + if (attributes != null && isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) { + // 获取注解的value 属性值 + Object value = attributes.get("value"); + if (value instanceof String) { + String strVal = (String) value; + // 判断是否存在值 + if (StringUtils.hasLength(strVal)) { + if (beanName != null && !strVal.equals(beanName)) { + throw new IllegalStateException("Stereotype annotations suggest inconsistent " + + "component names: '" + beanName + "' versus '" + strVal + "'"); + } + // beanName = value属性值 + beanName = strVal; + } + } + } + } + return beanName; + } + +``` + +```java +@Service(value = "dhc") +public class DemoService { + +} +``` + + + + + + + +- `org.springframework.context.annotation.AnnotationBeanNameGenerator#buildDefaultBeanName(org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.support.BeanDefinitionRegistry)` + - `org.springframework.context.annotation.AnnotationBeanNameGenerator#buildDefaultBeanName(org.springframework.beans.factory.config.BeanDefinition)` + + + +```JAVA + protected String buildDefaultBeanName(BeanDefinition definition) { + // 获取bean class name + String beanClassName = definition.getBeanClassName(); + Assert.state(beanClassName != null, "No bean class name set"); + // 获取短类名, + String shortClassName = ClassUtils.getShortName(beanClassName); + // 第一个字母小写 + return Introspector.decapitalize(shortClassName); + } + +``` + +```JAVA +@Configuration +public class BeanConfig { + @Scope(value =ConfigurableBeanFactory.SCOPE_PROTOTYPE) + @Bean(value = "hc") + public Ubean f() { + return new Ubean(); + } +} + +``` + + + + + + + +#### org.springframework.context.annotation.ClassPathBeanDefinitionScanner#postProcessBeanDefinition + +- 这个方法没什么难点,直接是set方法 + +```java + protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) { + beanDefinition.applyDefaults(this.beanDefinitionDefaults); + if (this.autowireCandidatePatterns != null) { + beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName)); + } + } + +``` + +```java + public void applyDefaults(BeanDefinitionDefaults defaults) { + setLazyInit(defaults.isLazyInit()); + setAutowireMode(defaults.getAutowireMode()); + setDependencyCheck(defaults.getDependencyCheck()); + setInitMethodName(defaults.getInitMethodName()); + setEnforceInitMethod(false); + setDestroyMethodName(defaults.getDestroyMethodName()); + setEnforceDestroyMethod(false); + } + +``` + +#### org.springframework.context.annotation.AnnotationConfigUtils#processCommonDefinitionAnnotations(org.springframework.beans.factory.annotation.AnnotatedBeanDefinition) + +```java + public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) { + processCommonDefinitionAnnotations(abd, abd.getMetadata()); + } + +``` + +```java +static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) { + // 获取 lazy 注解 + AnnotationAttributes lazy = attributesFor(metadata, Lazy.class); + if (lazy != null) { + abd.setLazyInit(lazy.getBoolean("value")); + } else if (abd.getMetadata() != metadata) { + lazy = attributesFor(abd.getMetadata(), Lazy.class); + if (lazy != null) { + abd.setLazyInit(lazy.getBoolean("value")); + } + } + + if (metadata.isAnnotated(Primary.class.getName())) { + abd.setPrimary(true); + } + AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class); + if (dependsOn != null) { + abd.setDependsOn(dependsOn.getStringArray("value")); + } + + AnnotationAttributes role = attributesFor(metadata, Role.class); + if (role != null) { + abd.setRole(role.getNumber("value").intValue()); + } + AnnotationAttributes description = attributesFor(metadata, Description.class); + if (description != null) { + abd.setDescription(description.getString("value")); + } + } +``` + + + +- 方法思路: + 1. 获取注解的属性值 + 2. 设置注解属性 + + + + + +#### org.springframework.context.annotation.ClassPathBeanDefinitionScanner#checkCandidate + +- 重复检查 + +```java + protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException { + // 判断当前 beanName 是否在注册表中 + if (!this.registry.containsBeanDefinition(beanName)) { + return true; + } + // 从注册表中获取 + BeanDefinition existingDef = this.registry.getBeanDefinition(beanName); + // 当前的bean + BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition(); + if (originatingDef != null) { + existingDef = originatingDef; + } + if (isCompatible(beanDefinition, existingDef)) { + return false; + } + throw new ConflictingBeanDefinitionException("Annotation-specified bean name '" + beanName + + "' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, " + + "non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]"); + } + +``` + + + + + +#### org.springframework.context.annotation.AnnotationConfigUtils#applyScopedProxyMode + + + +```JAVA + static BeanDefinitionHolder applyScopedProxyMode( + ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) { + + ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode(); + if (scopedProxyMode.equals(ScopedProxyMode.NO)) { + return definition; + } + boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS); + // 创建代理对象 + return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass); + } + +``` + diff --git a/docs/Spring/clazz/Spring-自定义标签解析.md b/docs/Spring/clazz/Spring-自定义标签解析.md new file mode 100644 index 0000000..8a700f8 --- /dev/null +++ b/docs/Spring/clazz/Spring-自定义标签解析.md @@ -0,0 +1,658 @@ +# Spring 自定义标签解析 +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) +- 与自定义标签解析相关的类 + 1. `org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser` + 2. `org.springframework.beans.factory.xml.NamespaceHandlerSupport` + +- 开始源码之前先搭建一个环境 + + +## 环境搭建 +- 创建对象 +```java +public class UserXtd { + private String userName; + private String emailAddress; + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getEmailAddress() { + return emailAddress; + } + + public void setEmailAddress(String emailAddress) { + this.emailAddress = emailAddress; + } +} +``` +- 创建 xsd 文件 +```xml + + + + + + + + + + + +``` +- 创建 namespaceHandler +```java +public class UserNamespaceHandler extends NamespaceHandlerSupport { + @Override + public void init() { + registerBeanDefinitionParser("myUser", new UserBeanDefinitionParser()); + } +} +``` +- 创建 beanDefinitionParser +```java +public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { + /** + * 标签对应class + * @param element the {@code Element} that is being parsed + * @return + */ + @Override + protected Class> getBeanClass(Element element) { + return UserXtd.class; + } + + + @Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + // 获取 userName 标签属性值 + String name = element.getAttribute("userName"); + // 获取 emailAddress 标签属性值 + String address = element.getAttribute("emailAddress"); + + if (StringUtils.hasText(name)) { + builder.addPropertyValue("userName", name); + } + if (StringUtils.hasText(address)) { + builder.addPropertyValue("emailAddress", address); + } + } +} + +``` +- 创建 resource/META-INF/spring.handlers +```text +http\://www.huifer.com/schema/user=com.huifer.source.spring.parser.UserNamespaceHandler +``` +- 创建 resource/META-INF/spring.schemas +```text +http\://www.huifer.com/schema/user.xsd=META-INF/spring-test.xsd +``` +- 创建测试用例xml +```xml + + + + + + +``` +- 创建 Java 运行方法 +```java +/** + * 自定义标签测试用例 + */ +public class XSDDemo { + public static void main(String[] args) { + ApplicationContext applicationContext = new ClassPathXmlApplicationContext("XTD-xml.xml"); + UserXtd user = (UserXtd) applicationContext.getBean("testUserBean"); + System.out.println(user.getEmailAddress()); + } +} +``` +- 这里我们希望输出结果是`huifer97@163.com`,运行后结果也确实是`huifer97@163.com` + +## 解析 DefaultNamespaceHandlerResolver +- 入口方法`org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions` +```java + 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 { + // 非spring 默认标签解析 + delegate.parseCustomElement(ele); + } + } + } + } + else { + delegate.parseCustomElement(root); + } + } + +``` +- 调用链路 +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(org.w3c.dom.Element)` + - `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)` + +```java + /** + * Parse a custom element (outside of the default namespace). + * + * 自定义标签解析 + * + * @param ele the element to parse + * @param containingBd the containing bean definition (if any) + * @return the resulting bean definition + */ + @Nullable + 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)); + } + +``` + + + +- `http://www.huifer.com/schema/user`和我们定义的xsd文件中的url相同,如何找到对应的NamespaceHandler,在`META-INF/spring.handlers`中有定义, + + `http\://www.huifer.com/schema/user=com.huifer.source.spring.parser.UserNamespaceHandler` + + `NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);`这行代码就是获取`spring.handlers`中的定义 + +- 处理方法`org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve` + + + +```java + /** + * Locate the {@link NamespaceHandler} for the supplied namespace URI + * from the configured mappings. + * + * 根据 namespaceUri 获取对应的 {@link NamespaceHandler} + * @param namespaceUri the relevant namespace URI + * @return the located {@link NamespaceHandler}, or {@code null} if none found + */ + @Override + @Nullable + public NamespaceHandler resolve(String namespaceUri) { + // 获取handlerMapping + Map handlerMappings = getHandlerMappings(); + // 从 handlerMapping 中获取类名 + 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); + // 调用init()方法,自定义类中实现 + namespaceHandler.init(); + // 放入缓存 + handlerMappings.put(namespaceUri, namespaceHandler); + // 返回自定义的 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); + } + } + } + +``` + + + +- `org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#getHandlerMappings`跟踪这个方法 + +```JAVA + /** + * Load the specified NamespaceHandler mappings lazily. + * + * 获取handlerMappings + */ + private Map getHandlerMappings() { + Map handlerMappings = this.handlerMappings; + } +``` + + + + + +- 这里直接存在数据了,他是从什么时候加载的? + +- `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions` + + 这个方法在注册bean定义的时候调用 + + ```java + public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { + BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); + int countBefore = getRegistry().getBeanDefinitionCount(); + // 注册方法 + // createReaderContext 初始化HandlerMapping + documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); + return getRegistry().getBeanDefinitionCount() - countBefore; + } + + ``` + +- 继续跟踪`createReaderContext` + + ```java + org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createReaderContext + ``` + + ```java + public XmlReaderContext createReaderContext(Resource resource) { + return new XmlReaderContext(resource, this.problemReporter, this.eventListener, + this.sourceExtractor, this, getNamespaceHandlerResolver()); + } + + ``` + +- 继续跟踪`getNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#getNamespaceHandlerResolver` + + ```java + public NamespaceHandlerResolver getNamespaceHandlerResolver() { + if (this.namespaceHandlerResolver == null) { + this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver(); + } + return this.namespaceHandlerResolver; + } + + ``` + +- 继续跟踪`createDefaultNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createDefaultNamespaceHandlerResolver` + + ```java + protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() { + ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader()); + return new DefaultNamespaceHandlerResolver(cl); + } + ``` + + + +- 继续跟踪`DefaultNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver` + + ```java + public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) { + this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); + } + + ``` + + 他回到了我们之前疑问的地方 `handlerMappings` 如何出现的 + + 断点 + +  + + ```JAVA + public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) { + this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); + } + ``` + + `public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";` + +  + + 此时还是空 + + 走完 + +  + + ```java + @Override + public String toString() { + return "NamespaceHandlerResolver using mappings " + getHandlerMappings(); + } + + ``` + + + +```JAVA + /** + * Load the specified NamespaceHandler mappings lazily. + * + * 获取handlerMappings + */ + private Map getHandlerMappings() { + Map handlerMappings = this.handlerMappings; + // 缓存不存在 + if (handlerMappings == null) { + synchronized (this) { + handlerMappings = this.handlerMappings; + if (handlerMappings == null) { + if (logger.isTraceEnabled()) { + logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]"); + } + try { + // 将本地文件读出 + Properties mappings = + PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader); + if (logger.isTraceEnabled()) { + logger.trace("Loaded NamespaceHandler mappings: " + mappings); + } + handlerMappings = new ConcurrentHashMap<>(mappings.size()); + // 转换成map结构 + CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings); + this.handlerMappings = handlerMappings; + } + catch (IOException ex) { + throw new IllegalStateException( + "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex); + } + } + } + } + return handlerMappings; + } + +``` + + + + + + + + + +## org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#resolve + +```java + @Override + @Nullable + public NamespaceHandler resolve(String namespaceUri) { + // 获取handlerMapping + Map handlerMappings = getHandlerMappings(); + // 从 handlerMapping 中获取类名 + 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); + // 调用init()方法,自定义类中实现 + namespaceHandler.init(); + // 放入缓存 + handlerMappings.put(namespaceUri, namespaceHandler); + // 返回自定义的 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); + } + } + } + +``` + +执行`init`方法 + +```java +public class UserNamespaceHandler extends NamespaceHandlerSupport { + @Override + public void init() { + registerBeanDefinitionParser("myUser", new UserBeanDefinitionParser()); + } +} +``` + +```java + /** + * Subclasses can call this to register the supplied {@link BeanDefinitionParser} to + * handle the specified element. The element name is the local (non-namespace qualified) + * name. + * + * 将标签名称,标签解析类放入 + */ + protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) { + this.parsers.put(elementName, parser); + } + +``` + + + +- 方法走完,回到开始的方法 + + ```java + /** + * Parse a custom element (outside of the default namespace). + * + * 自定义标签解析 + * + * @param ele the element to parse + * @param containingBd the containing bean definition (if any) + * @return the resulting bean definition + */ + @Nullable + public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { + // 自定义标签解析 + String namespaceUri = getNamespaceURI(ele); + if (namespaceUri == null) { + return null; + } + // 根据命名空间获取处理类 + // org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve + 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)); + } + + ``` + + + + + + + + + +## org.springframework.beans.factory.xml.NamespaceHandler#parse + +- `org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse` + + ```java + @Override + @Nullable + public BeanDefinition parse(Element element, ParserContext parserContext) { + BeanDefinitionParser parser = findParserForElement(element, parserContext); + return (parser != null ? parser.parse(element, parserContext) : null); + } + + ``` + +### org.springframework.beans.factory.xml.NamespaceHandlerSupport#findParserForElement + +```java + @Nullable + private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { + // 获取标签名称 + String localName = parserContext.getDelegate().getLocalName(element); + // 在map中获取对应的标签解析类 + BeanDefinitionParser parser = this.parsers.get(localName); + // 空报错 + if (parser == null) { + parserContext.getReaderContext().fatal( + "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); + } + // 不为空返回 + return parser; + } + +``` + + + +### org.springframework.beans.factory.xml.BeanDefinitionParser#parse + +- `org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parse` + +```java + public final BeanDefinition parse(Element element, ParserContext parserContext) { + /** + * {@link AbstractSingleBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)} + */ + AbstractBeanDefinition definition = parseInternal(element, parserContext); + + + } +``` + +### org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#parseInternal + +```java +@Override + protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); + String parentName = getParentName(element); + if (parentName != null) { + builder.getRawBeanDefinition().setParentName(parentName); + } + // 调用自己实现的方法 com.huifer.source.spring.parser.UserBeanDefinitionParser.getBeanClass + Class> beanClass = getBeanClass(element); + if (beanClass != null) { + builder.getRawBeanDefinition().setBeanClass(beanClass); + } + else { + // getBeanClassName 同样也是可以在自定义的解析类中实现 + 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. + // 设置scope + builder.setScope(containingBd.getScope()); + } + if (parserContext.isDefaultLazyInit()) { + // Default-lazy-init applies to custom bean definitions as well. + // 设置 lazy-init + builder.setLazyInit(true); + } + + // 执行解析方法,在自定义解析类中存在com.huifer.source.spring.parser.UserBeanDefinitionParser.doParse + doParse(element, parserContext, builder); + return builder.getBeanDefinition(); + } +``` + + + + + +执行`com.huifer.source.spring.parser.UserBeanDefinitionParser#doParse` + +```JAVA +@Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + // 获取 userName 标签属性值 + String name = element.getAttribute("userName"); + // 获取 emailAddress 标签属性值 + String address = element.getAttribute("emailAddress"); + + if (StringUtils.hasText(name)) { + builder.addPropertyValue("userName", name); + } + if (StringUtils.hasText(address)) { + builder.addPropertyValue("emailAddress", address); + } + } +``` + + + + + diff --git a/images/spring/image-20200109084131415.png b/images/spring/image-20200109084131415.png new file mode 100644 index 0000000..6d99aa1 Binary files /dev/null and b/images/spring/image-20200109084131415.png differ diff --git a/images/spring/image-20200109085606240.png b/images/spring/image-20200109085606240.png new file mode 100644 index 0000000..61883bf Binary files /dev/null and b/images/spring/image-20200109085606240.png differ diff --git a/images/spring/image-20200109090456547.png b/images/spring/image-20200109090456547.png new file mode 100644 index 0000000..19e745c Binary files /dev/null and b/images/spring/image-20200109090456547.png differ diff --git a/images/spring/image-20200109090655157.png b/images/spring/image-20200109090655157.png new file mode 100644 index 0000000..97c431c Binary files /dev/null and b/images/spring/image-20200109090655157.png differ diff --git a/images/spring/image-20200109091216505.png b/images/spring/image-20200109091216505.png new file mode 100644 index 0000000..cbc2d48 Binary files /dev/null and b/images/spring/image-20200109091216505.png differ diff --git a/images/spring/image-20200109092801572.png b/images/spring/image-20200109092801572.png new file mode 100644 index 0000000..043a9ca Binary files /dev/null and b/images/spring/image-20200109092801572.png differ diff --git a/images/spring/image-20200109093242494.png b/images/spring/image-20200109093242494.png new file mode 100644 index 0000000..8d8077f Binary files /dev/null and b/images/spring/image-20200109093242494.png differ diff --git a/images/spring/image-20200109094032421.png b/images/spring/image-20200109094032421.png new file mode 100644 index 0000000..a8dcfb1 Binary files /dev/null and b/images/spring/image-20200109094032421.png differ diff --git a/images/spring/image-20200109094649217.png b/images/spring/image-20200109094649217.png new file mode 100644 index 0000000..2c2b1f2 Binary files /dev/null and b/images/spring/image-20200109094649217.png differ diff --git a/images/spring/image-20200109094654409.png b/images/spring/image-20200109094654409.png new file mode 100644 index 0000000..2c2b1f2 Binary files /dev/null and b/images/spring/image-20200109094654409.png differ diff --git a/images/spring/image-20200109150841916.png b/images/spring/image-20200109150841916.png new file mode 100644 index 0000000..c85d445 Binary files /dev/null and b/images/spring/image-20200109150841916.png differ diff --git a/images/spring/image-20200110093044672.png b/images/spring/image-20200110093044672.png new file mode 100644 index 0000000..514b59c Binary files /dev/null and b/images/spring/image-20200110093044672.png differ diff --git a/images/spring/image-20200115083744268.png b/images/spring/image-20200115083744268.png new file mode 100644 index 0000000..8a465cd Binary files /dev/null and b/images/spring/image-20200115083744268.png differ diff --git a/images/spring/image-20200115084031725.png b/images/spring/image-20200115084031725.png new file mode 100644 index 0000000..6742458 Binary files /dev/null and b/images/spring/image-20200115084031725.png differ diff --git a/images/spring/image-20200115093602651.png b/images/spring/image-20200115093602651.png new file mode 100644 index 0000000..fa04a3c Binary files /dev/null and b/images/spring/image-20200115093602651.png differ diff --git a/images/spring/image-20200115105941265.png b/images/spring/image-20200115105941265.png new file mode 100644 index 0000000..88c456b Binary files /dev/null and b/images/spring/image-20200115105941265.png differ diff --git a/images/spring/image-20200115141708702.png b/images/spring/image-20200115141708702.png new file mode 100644 index 0000000..2c1ada0 Binary files /dev/null and b/images/spring/image-20200115141708702.png differ diff --git a/images/spring/image-20200115143315633.png b/images/spring/image-20200115143315633.png new file mode 100644 index 0000000..6edee36 Binary files /dev/null and b/images/spring/image-20200115143315633.png differ diff --git a/images/spring/image-20200115143456554.png b/images/spring/image-20200115143456554.png new file mode 100644 index 0000000..d19ba94 Binary files /dev/null and b/images/spring/image-20200115143456554.png differ diff --git a/images/spring/image-20200116085344737.png b/images/spring/image-20200116085344737.png new file mode 100644 index 0000000..6f39a30 Binary files /dev/null and b/images/spring/image-20200116085344737.png differ diff --git a/images/spring/image-20200116085423073.png b/images/spring/image-20200116085423073.png new file mode 100644 index 0000000..c40cad2 Binary files /dev/null and b/images/spring/image-20200116085423073.png differ diff --git a/images/spring/image-20200116085726577.png b/images/spring/image-20200116085726577.png new file mode 100644 index 0000000..31a3481 Binary files /dev/null and b/images/spring/image-20200116085726577.png differ diff --git a/images/spring/image-20200116085737632.png b/images/spring/image-20200116085737632.png new file mode 100644 index 0000000..ae8f4cb Binary files /dev/null and b/images/spring/image-20200116085737632.png differ diff --git a/images/spring/image-20200116085927359.png b/images/spring/image-20200116085927359.png new file mode 100644 index 0000000..7a02538 Binary files /dev/null and b/images/spring/image-20200116085927359.png differ diff --git a/images/spring/image-20200116092259944.png b/images/spring/image-20200116092259944.png new file mode 100644 index 0000000..0d20a5a Binary files /dev/null and b/images/spring/image-20200116092259944.png differ diff --git a/images/spring/image-20200116141838601.png b/images/spring/image-20200116141838601.png new file mode 100644 index 0000000..e4ee61b Binary files /dev/null and b/images/spring/image-20200116141838601.png differ diff --git a/images/spring/image-20200116141932486.png b/images/spring/image-20200116141932486.png new file mode 100644 index 0000000..8e06086 Binary files /dev/null and b/images/spring/image-20200116141932486.png differ diff --git a/images/spring/image-20200119085346675.png b/images/spring/image-20200119085346675.png new file mode 100644 index 0000000..2c23ebb Binary files /dev/null and b/images/spring/image-20200119085346675.png differ diff --git a/images/spring/image-20200119085655734.png b/images/spring/image-20200119085655734.png new file mode 100644 index 0000000..18bf79e Binary files /dev/null and b/images/spring/image-20200119085655734.png differ diff --git a/images/spring/image-20200119101017989.png b/images/spring/image-20200119101017989.png new file mode 100644 index 0000000..c8b3ad9 Binary files /dev/null and b/images/spring/image-20200119101017989.png differ diff --git a/images/spring/image-20200119101026726.png b/images/spring/image-20200119101026726.png new file mode 100644 index 0000000..14b6c3e Binary files /dev/null and b/images/spring/image-20200119101026726.png differ diff --git a/images/spring/image-20200119101107820.png b/images/spring/image-20200119101107820.png new file mode 100644 index 0000000..e2546cb Binary files /dev/null and b/images/spring/image-20200119101107820.png differ diff --git a/images/spring/image-20200119101516591.png b/images/spring/image-20200119101516591.png new file mode 100644 index 0000000..4236551 Binary files /dev/null and b/images/spring/image-20200119101516591.png differ
+ * 做3个判断 + *
Default is {@link Ordered#LOWEST_PRECEDENCE}. + * + * 启动顺序,默认integer最大值 + * @see Ordered#getOrder() + */ + int value() default Ordered.LOWEST_PRECEDENCE; + +} +``` + + + +最终返回 + + + + + + + + + + + +## findAnnotation + +- `org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.Method, java.lang.Class)` + + ```java + @SuppressWarnings("unchecked") + @Nullable + public static A findAnnotation(Method method, @Nullable Class annotationType) { + Assert.notNull(method, "Method must not be null"); + if (annotationType == null) { + return null; + } + // 创建注解缓存,key:被扫描的函数,value:注解 + AnnotationCacheKey cacheKey = new AnnotationCacheKey(method, annotationType); + // 从findAnnotationCache获取缓存 + A result = (A) findAnnotationCache.get(cacheKey); + + if (result == null) { + Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method); + // 寻找注解 + result = findAnnotation((AnnotatedElement) resolvedMethod, annotationType); + if (result == null) { + result = searchOnInterfaces(method, annotationType, method.getDeclaringClass().getInterfaces()); + } + + Class> clazz = method.getDeclaringClass(); + while (result == null) { + clazz = clazz.getSuperclass(); + if (clazz == null || clazz == Object.class) { + break; + } + Set annotatedMethods = getAnnotatedMethodsInBaseType(clazz); + if (!annotatedMethods.isEmpty()) { + for (Method annotatedMethod : annotatedMethods) { + if (isOverride(method, annotatedMethod)) { + Method resolvedSuperMethod = BridgeMethodResolver.findBridgedMethod(annotatedMethod); + result = findAnnotation((AnnotatedElement) resolvedSuperMethod, annotationType); + if (result != null) { + break; + } + } + } + } + if (result == null) { + result = searchOnInterfaces(method, annotationType, clazz.getInterfaces()); + } + } + + if (result != null) { + // 处理注解 + result = synthesizeAnnotation(result, method); + // 添加缓存 + findAnnotationCache.put(cacheKey, result); + } + } + // 返回 + return result; + } + + ``` + + + +- `org.springframework.core.annotation.AnnotationUtils.AnnotationCacheKey` + + ```java + private static final class AnnotationCacheKey implements Comparable { + + /** + * 带有注解的函数或者类 + */ + private final AnnotatedElement element; + + /** + * 注解 + */ + private final Class extends Annotation> annotationType; + + public AnnotationCacheKey(AnnotatedElement element, Class extends Annotation> annotationType) { + this.element = element; + this.annotationType = annotationType; + } + + } + ``` + + + +- `org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.AnnotatedElement, java.lang.Class)` + + ```java + @Nullable + public static A findAnnotation( + AnnotatedElement annotatedElement, @Nullable Class annotationType) { + // 注解类型不为空 + if (annotationType == null) { + return null; + } + + // Do NOT store result in the findAnnotationCache since doing so could break + // findAnnotation(Class, Class) and findAnnotation(Method, Class). + // 寻找注解 + A ann = findAnnotation(annotatedElement, annotationType, new HashSet<>()); + return (ann != null ? synthesizeAnnotation(ann, annotatedElement) : null); + } + + ``` + + + + + +- `org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.AnnotatedElement, java.lang.Class, java.util.Set)` + + ```java + @Nullable + private static A findAnnotation( + AnnotatedElement annotatedElement, Class annotationType, Set visited) { + try { + // 直接获取注解 + A annotation = annotatedElement.getDeclaredAnnotation(annotationType); + if (annotation != null) { + return annotation; + } + // 多级注解 + for (Annotation declaredAnn : getDeclaredAnnotations(annotatedElement)) { + Class extends Annotation> declaredType = declaredAnn.annotationType(); + // 注解是否 由java.lang.annotation提供 + if (!isInJavaLangAnnotationPackage(declaredType) && visited.add(declaredAnn)) { + annotation = findAnnotation((AnnotatedElement) declaredType, annotationType, visited); + if (annotation != null) { + return annotation; + } + } + } + } catch (Throwable ex) { + handleIntrospectionFailure(annotatedElement, ex); + } + return null; + } + + ``` + + + + + +- `synthesizeAnnotation`方法就不再重复一遍了可以看上文 + + + + + + + +## getValue + +- 测试用例 + + ```java + @Test + public void getValueFromAnnotation() throws Exception { + Method method = SimpleFoo.class.getMethod("something", Object.class); + Order order = findAnnotation(method, Order.class); + + assertEquals(1, getValue(order, VALUE)); + assertEquals(1, getValue(order)); + } + ``` + + + +- `org.springframework.core.annotation.AnnotationUtils#getValue(java.lang.annotation.Annotation, java.lang.String)` + +```java + @Nullable + public static Object getValue(@Nullable Annotation annotation, @Nullable String attributeName) { + if (annotation == null || !StringUtils.hasText(attributeName)) { + return null; + } + try { + // 根据attributeName获取注解对应函数 + Method method = annotation.annotationType().getDeclaredMethod(attributeName); + ReflectionUtils.makeAccessible(method); + // 反射执行方法 + return method.invoke(annotation); + } catch (NoSuchMethodException ex) { + return null; + } catch (InvocationTargetException ex) { + rethrowAnnotationConfigurationException(ex.getTargetException()); + throw new IllegalStateException("Could not obtain value for annotation attribute '" + + attributeName + "' in " + annotation, ex); + } catch (Throwable ex) { + handleIntrospectionFailure(annotation.getClass(), ex); + return null; + } + } + +``` + + + +```java + @Nullable + public static Object getValue(Annotation annotation) { + return getValue(annotation, VALUE); + } + +``` + + + + + + + +## getDefaultValue + +- `org.springframework.core.annotation.AnnotationUtils#getDefaultValue(java.lang.annotation.Annotation)` + + + +```java + @Nullable + public static Object getDefaultValue(Annotation annotation) { + return getDefaultValue(annotation, VALUE); + } + +``` + +```java + @Nullable + public static Object getDefaultValue( + @Nullable Class extends Annotation> annotationType, @Nullable String attributeName) { + + if (annotationType == null || !StringUtils.hasText(attributeName)) { + return null; + } + try { + // 直接获取defaultValue + return annotationType.getDeclaredMethod(attributeName).getDefaultValue(); + } catch (Throwable ex) { + handleIntrospectionFailure(annotationType, ex); + return null; + } + } + +``` + diff --git a/docs/Spring/clazz/Spring-BeanFactoryPostProcessor.md b/docs/Spring/clazz/Spring-BeanFactoryPostProcessor.md new file mode 100644 index 0000000..81fe47a --- /dev/null +++ b/docs/Spring/clazz/Spring-BeanFactoryPostProcessor.md @@ -0,0 +1,447 @@ +# Spring BeanFactoryPostProcessor +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) +- 作用: 定制或修改`BeanDefinition`的属性 + + +## Demo +```java +public class ChangeAttrBeanPostProcessor implements BeanFactoryPostProcessor { + private Set attr; + + public ChangeAttrBeanPostProcessor() { + attr = new HashSet<>(); + } + + public Set getAttr() { + return attr; + } + + public void setAttr(Set attr) { + this.attr = attr; + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames(); + for (String beanName : beanDefinitionNames) { + BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); + + StringValueResolver stringValueResolver = new StringValueResolver() { + @Override + public String resolveStringValue(String strVal) { + if (attr.contains(strVal)) { + return "隐藏属性"; + } + else { + return strVal; + } + } + }; + BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(stringValueResolver); + visitor.visitBeanDefinition(beanDefinition); + } + } +} +``` + +```java +public class BeanFactoryPostProcessorSourceCode { + public static void main(String[] args) { + ApplicationContext context = new ClassPathXmlApplicationContext("BeanFactoryPostProcessor-demo.xml"); + Apple apple = context.getBean("apple", Apple.class); + System.out.println(apple); + } +} +``` + +```xml + + + + + + hc + + + + + + + + +``` + + + +## 初始化 + +- `org.springframework.context.support.AbstractApplicationContext#refresh` + + ```JAVA + invokeBeanFactoryPostProcessors(beanFactory); + ``` + + ```JAVA + 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())); + } + } + + ``` + +- `org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List)` + + ```JAVA + public static void invokeBeanFactoryPostProcessors( + ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) { + + // Invoke BeanDefinitionRegistryPostProcessors first, if any. + Set processedBeans = new HashSet<>(); + // 判断是否为BeanDefinitionRegistry类 + if (beanFactory instanceof BeanDefinitionRegistry) { + BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; + // 存放 BeanFactoryPostProcessor + List regularPostProcessors = new ArrayList<>(); + // 存放 BeanDefinitionRegistryPostProcessor + List registryProcessors = new ArrayList<>(); + + // 2.首先处理入参中的beanFactoryPostProcessors + for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { + // 判断是否是BeanDefinitionRegistryPostProcessor + if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { + BeanDefinitionRegistryPostProcessor registryProcessor = + (BeanDefinitionRegistryPostProcessor) postProcessor; + // + registryProcessor.postProcessBeanDefinitionRegistry(registry); + // BeanDefinitionRegistryPostProcessor 添加 + // 执行 postProcessBeanFactory + registryProcessors.add(registryProcessor); + } + // 这部分else 内容就是 BeanFactoryPostProcessor + else { + // BeanFactoryPostProcessor 添加 + 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 currentRegistryProcessors = new ArrayList<>(); + + // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. + /** + * 调用实现{@link PriorityOrdered}\{@link BeanDefinitionRegistryPostProcessor} + * todo: 2020年1月16日 解析方法 + * {@link DefaultListableBeanFactory#getBeanNamesForType(java.lang.Class, boolean, boolean)} + */ + 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); + } + } + // 排序Order + 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! + // 配置文件中的 BeanFactoryPostProcessor 处理 + String[] postProcessorNames = + beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); + + // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, + // Ordered, and the rest. + List priorityOrderedPostProcessors = new ArrayList<>(); + List orderedPostProcessorNames = new ArrayList<>(); + List 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 orderedPostProcessors = new ArrayList<>(); + for (String postProcessorName : orderedPostProcessorNames) { + orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); + } + sortPostProcessors(orderedPostProcessors, beanFactory); + invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); + + // Finally, invoke all other BeanFactoryPostProcessors. + // 配置文件中自定义的 BeanFactoryPostProcessor 注册 + List nonOrderedPostProcessors = new ArrayList<>(); + 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(); + } + ``` + + + + + + + + + + + +## InstantiationAwareBeanPostProcessor + +```java + protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { + PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this); + } +``` + + + +```java + public static void registerBeanPostProcessors( + ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { + // 获取 BeanPostProcessor + 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. + // BeanPostProcessor 通过PriorityOrdered保证顺序 + List priorityOrderedPostProcessors = new ArrayList<>(); + // MergedBeanDefinitionPostProcessor + List internalPostProcessors = new ArrayList<>(); + // 有序的 BeanPostProcessor + List orderedPostProcessorNames = new ArrayList<>(); + // 无序的 BeanPostProcessor + List nonOrderedPostProcessorNames = new ArrayList<>(); + for (String ppName : postProcessorNames) { + if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { + BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); + priorityOrderedPostProcessors.add(pp); + // 类型判断放入相应的list + 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. + /** + * 有{@link org.springframework.core.annotation.Order} 相关操作 + */ + sortPostProcessors(priorityOrderedPostProcessors, beanFactory); + // 注册 BeanPostProcessor 和 PriorityOrdered 实现 + registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); + + // Next, register the BeanPostProcessors that implement Ordered. + List orderedPostProcessors = new ArrayList<>(); + for (String ppName : orderedPostProcessorNames) { + BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); + orderedPostProcessors.add(pp); + if (pp instanceof MergedBeanDefinitionPostProcessor) { + internalPostProcessors.add(pp); + } + } + sortPostProcessors(orderedPostProcessors, beanFactory); + // 注册 实现Order 和 BeanPostProcessor + registerBeanPostProcessors(beanFactory, orderedPostProcessors); + + // Now, register all regular BeanPostProcessors. + List nonOrderedPostProcessors = new ArrayList<>(); + for (String ppName : nonOrderedPostProcessorNames) { + BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); + nonOrderedPostProcessors.add(pp); + if (pp instanceof MergedBeanDefinitionPostProcessor) { + internalPostProcessors.add(pp); + } + } + // 注册无序的 BeanPostProcessor + registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); + + // Finally, re-register all internal BeanPostProcessors. + sortPostProcessors(internalPostProcessors, beanFactory); + // 注册 MergedBeanDefinitionPostProcessor + 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). + // 添加 ApplicationListenerDetector + beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); + } + + +``` + + + +- 测试用Bean + +```java +public class DemoInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { + @Override + public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException { + System.out.println("init bean beanClass = " + beanClass.getSimpleName() + " beanName = " + beanName); + return null; + } +} +``` + + + +- 按照笔者的注释,可以知道`DemoInstantiationAwareBeanPostProcessor` 这个类是一个无序Bean + +  + + + + + +- 注册方法信息截图 + + + + + + + +### 使用阶段(调用阶段) + +在`org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])`中有如下代码 + +```JAVA + Object bean = resolveBeforeInstantiation(beanName, mbdToUse); +``` + +- `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation` + +```JAVA +@Nullable + protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { + Object bean = null; + if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { + // Make sure bean class is actually resolved at this point. + if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { + Class> targetType = determineTargetType(beanName, mbd); + if (targetType != null) { + /** + * 主要实现{@link org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(java.lang.Class, java.lang.String)} + */ + bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); + if (bean != null) { + bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); + } + } + } + mbd.beforeInstantiationResolved = (bean != null); + } + return bean; + } +``` + +- `org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation` + +```JAVA + @Nullable + protected Object applyBeanPostProcessorsBeforeInstantiation(Class> beanClass, String beanName) { + for (BeanPostProcessor bp : getBeanPostProcessors()) { + if (bp instanceof InstantiationAwareBeanPostProcessor) { + InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; + // 调用自定义实现 + Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); + if (result != null) { + return result; + } + } + } + return null; + } + +``` + +这个地方已经可以看到`InstantiationAwareBeanPostProcessor`出现了,并且调用了方法`postProcessBeforeInstantiation`,此处就可以调用我们的自定义方法了 + + \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-DefaultSingletonBeanRegistry.md b/docs/Spring/clazz/Spring-DefaultSingletonBeanRegistry.md new file mode 100644 index 0000000..ccd1231 --- /dev/null +++ b/docs/Spring/clazz/Spring-DefaultSingletonBeanRegistry.md @@ -0,0 +1,278 @@ +# DefaultSingletonBeanRegistry +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) +- 源码路径: `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry` +- 官方提供的测试类: `org.springframework.beans.factory.support.DefaultSingletonBeanRegistryTests` + +类图 + +## 注册方法解析 +- 从名字可以看出这是一个单例对象的注册类 +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.registerSingleton` + + + +- 测试用例出发 + + ```java + @Test + public void testSingletons() { + DefaultSingletonBeanRegistry beanRegistry = new DefaultSingletonBeanRegistry(); + + TestBean tb = new TestBean(); + beanRegistry.registerSingleton("tb", tb); + assertSame(tb, beanRegistry.getSingleton("tb")); + + TestBean tb2 = (TestBean) beanRegistry.getSingleton("tb2", new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return new TestBean(); + } + }); + assertSame(tb2, beanRegistry.getSingleton("tb2")); + + assertSame(tb, beanRegistry.getSingleton("tb")); + assertSame(tb2, beanRegistry.getSingleton("tb2")); + assertEquals(2, beanRegistry.getSingletonCount()); + String[] names = beanRegistry.getSingletonNames(); + assertEquals(2, names.length); + assertEquals("tb", names[0]); + assertEquals("tb2", names[1]); + + beanRegistry.destroySingletons(); + assertEquals(0, beanRegistry.getSingletonCount()); + assertEquals(0, beanRegistry.getSingletonNames().length); + } + + ``` + + + +- 第一个关注的方法`org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#registerSingleton` 注册单例对象 + +```java + /** + * 注册一个单例对象 + * + * @param beanName the name of the bean + * @param singletonObject the existing singleton object + * @throws IllegalStateException + */ + @Override + public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { + Assert.notNull(beanName, "Bean name must not be null"); + Assert.notNull(singletonObject, "Singleton object must not be null"); + synchronized (this.singletonObjects) { + // 通过beanName获取单例对象 + Object oldObject = this.singletonObjects.get(beanName); + // 不为空异常 + if (oldObject != null) { + throw new IllegalStateException("Could not register object [" + singletonObject + + "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound"); + } + // 添加方法 + addSingleton(beanName, singletonObject); + } + } + +``` +```java + /** + * Add the given singleton object to the singleton cache of this factory. + * To be called for eager registration of singletons. + * + * 添加单例对象的操作方法 + * + * @param beanName the name of the bean + * @param singletonObject the singleton object + */ + protected void addSingleton(String beanName, Object singletonObject) { + synchronized (this.singletonObjects) { + this.singletonObjects.put(beanName, singletonObject); + this.singletonFactories.remove(beanName); + this.earlySingletonObjects.remove(beanName); + this.registeredSingletons.add(beanName); + } + } +``` +- 这些变量是什么 +```java + /** + * 单例对象的缓存: beanName -> Object + */ + private final Map singletonObjects = new ConcurrentHashMap<>(256); + + /** + * 单例工厂的缓存: beanName -> ObjectFactory。 + */ + private final Map> singletonFactories = new HashMap<>(16); + + /** + * 延迟加载的单例对象缓存: beanName -> Object + */ + private final Map earlySingletonObjects = new HashMap<>(16); + + /** + * 已经注册过的单例对象名称(beanName) + */ + private final Set registeredSingletons = new LinkedHashSet<>(256); + + /** + * 当前正在创建的单例对象名称(beanName) + */ + private final Set singletonsCurrentlyInCreation = + Collections.newSetFromMap(new ConcurrentHashMap<>(16)); + + private final Set inCreationCheckExclusions = + Collections.newSetFromMap(new ConcurrentHashMap<>(16)); + /** + * 摧毁单例对象 + */ + private final Map disposableBeans = new LinkedHashMap<>(); + private final Map> containedBeanMap = new ConcurrentHashMap<>(16); + /** + * bean 和beanName的关系 + */ + private final Map> dependentBeanMap = new ConcurrentHashMap<>(64); + /** + * bean 依赖关系 beanName -> 依赖关系 + */ + private final Map> dependenciesForBeanMap = new ConcurrentHashMap<>(64); + /** + * 异常列表 + */ + @Nullable + private Set suppressedExceptions; + /** + * 标记是否在 destroySingletons 上 + */ + private boolean singletonsCurrentlyInDestruction = false; + +``` + +- 注册方法至此结束 + +## 获取方法解析 +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(java.lang.String)` +```java + @Override + @Nullable + public Object getSingleton(String beanName) { + return getSingleton(beanName, true); + } +``` + +```java + @Nullable + protected Object getSingleton(String beanName, boolean allowEarlyReference) { + // 从列表中获取单例对象 + Object singletonObject = this.singletonObjects.get(beanName); + // 判断当前beanName是否存在 + if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { + synchronized (this.singletonObjects) { + // 从延迟加载中获取 + singletonObject = this.earlySingletonObjects.get(beanName); + if (singletonObject == null && allowEarlyReference) { + // 从singletonFactories获取ObjectFactory + ObjectFactory> singletonFactory = this.singletonFactories.get(beanName); + if (singletonFactory != null) { + // 获取对象 + singletonObject = singletonFactory.getObject(); + // 加入缓存 + this.earlySingletonObjects.put(beanName, singletonObject); + this.singletonFactories.remove(beanName); + } + } + } + } + return singletonObject; + } + +``` + +- 获取单例对象的本质就是从map中获取 ObjectFactory 进而执行 getObject() +`ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);` +- 测试方法 +```java + + TestBean tb2 = (TestBean) beanRegistry.getSingleton("tb2", new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return new TestBean(); + } + }); +``` + +- 获取单例对象的方式 + +```java +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; + } + } +``` + +不难发现最后都是通过`singletonObject = singletonFactory.getObject();`进行获取 + +这个地方的方法实际上就是测试类中的 + +```java +new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return new TestBean(); + } + } +``` + +通过`getObject`就可以获取当前对象 \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-OrderComparator.md b/docs/Spring/clazz/Spring-OrderComparator.md new file mode 100644 index 0000000..173f546 --- /dev/null +++ b/docs/Spring/clazz/Spring-OrderComparator.md @@ -0,0 +1,98 @@ +# Spring OrderComparator +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) + + +```java + private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) { + boolean p1 = (o1 instanceof PriorityOrdered); + boolean p2 = (o2 instanceof PriorityOrdered); + if (p1 && !p2) { + return -1; + } else if (p2 && !p1) { + return 1; + } + + int i1 = getOrder(o1, sourceProvider); + int i2 = getOrder(o2, sourceProvider); + // 对比两个Order值得大小返回 + return Integer.compare(i1, i2); + } + +``` + +```java + private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) { + Integer order = null; + if (obj != null && sourceProvider != null) { + // 获取Order + Object orderSource = sourceProvider.getOrderSource(obj); + if (orderSource != null) { + if (orderSource.getClass().isArray()) { + // 获取 OrderSourceProvider 的值 + Object[] sources = ObjectUtils.toObjectArray(orderSource); + for (Object source : sources) { + // 找 order 返回 + order = findOrder(source); + if (order != null) { + break; + } + } + } else { + // 寻找 order + order = findOrder(orderSource); + } + } + } + return (order != null ? order : getOrder(obj)); + } + +``` + +- 测试用例 +```java + @Test + public void compareWithSourceProviderArray() { + Comparator customComparator = this.comparator.withSourceProvider( + new TestSourceProvider(5L, new Object[]{new StubOrdered(10), new StubOrdered(-25)})); + assertEquals(-1, customComparator.compare(5L, new Object())); + } + +``` + + + + + +```java + @Nullable + protected Integer findOrder(Object obj) { + // 获取Ordered实现类 + return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null); + } + +``` + +```java + private static final class StubOrdered implements Ordered { + + private final int order; + + + public StubOrdered(int order) { + this.order = order; + } + + @Override + public int getOrder() { + return this.order; + } + } + +``` + + + + + +最终`Integer.compare(i1, i2)`比较返回 OK ! \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-scan.md b/docs/Spring/clazz/Spring-scan.md new file mode 100644 index 0000000..5e03fe9 --- /dev/null +++ b/docs/Spring/clazz/Spring-scan.md @@ -0,0 +1,534 @@ +# Spring scan +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) + +## 解析 +- Spring 注解形式使用有下面两种方式 + 1. 通过`AnnotationConfigApplicationContext`参数:扫描包 + 2. 通过xml配置`context:component-scan`属性`base-package` +```java + AnnotationConfigApplicationContext aac = + new AnnotationConfigApplicationContext("com.huifer.source.spring.ann"); +``` +```xml + + +``` + +- 目标明确开始找入口方法 +- `AnnotationConfigApplicationContext`直接点进去看就找到了 +```java +public AnnotationConfigApplicationContext(String... basePackages) { + this(); + // 扫描包 + scan(basePackages); + refresh(); + } +``` +- `context:component-scan`寻找方式:冒号`:`钱+NamespaceHandler 或者全文搜索`component-scan`,最终找到`org.springframework.context.config.ContextNamespaceHandler` +```java +public class ContextNamespaceHandler extends NamespaceHandlerSupport { + + @Override + public void init() { + registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); + registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); + registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); + registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); + registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser()); + registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); + registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser()); + registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser()); + } + +} +``` + +### org.springframework.context.annotation.ComponentScanBeanDefinitionParser + + + +- 实现`BeanDefinitionParser`直接看`parse`方法 +```java + @Override + @Nullable + public BeanDefinition parse(Element element, ParserContext parserContext) { + // 获取 base-package 属性值 + String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); + // 处理 ${} + basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); + // 分隔符`,;\t\n`切分 + String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, + ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); + + // Actually scan for bean definitions and register them. + // 扫描对象创建 + ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); + // 执行扫描方法 + Set beanDefinitions = scanner.doScan(basePackages); + // 注册组件,触发监听 + registerComponents(parserContext.getReaderContext(), beanDefinitions, element); + + return null; + } + +``` + +- 回过头看`AnnotationConfigApplicationContext` +### org.springframework.context.annotation.AnnotationConfigApplicationContext +```java +public AnnotationConfigApplicationContext(String... basePackages) { + this(); + // 扫描包 + scan(basePackages); + refresh(); + } +``` +```java + private final ClassPathBeanDefinitionScanner scanner; + + @Override + public void scan(String... basePackages) { + Assert.notEmpty(basePackages, "At least one base package must be specified"); + this.scanner.scan(basePackages); + } + +``` +- `org.springframework.context.annotation.ClassPathBeanDefinitionScanner.scan` +```java +public int scan(String... basePackages) { + + // 获取bean数量 + 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); + } +``` + +- 这个地方`doScan`似曾相识,他就是`org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse`中的`doScan`,下一步解析doScan + +### org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan + + + +```java + protected Set doScan(String... basePackages) { + Assert.notEmpty(basePackages, "At least one base package must be specified"); + Set beanDefinitions = new LinkedHashSet<>(); + for (String basePackage : basePackages) { + // 寻找组件 + Set candidates = findCandidateComponents(basePackage); + for (BeanDefinition candidate : candidates) { + // bean 作用域设置 + ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); + // 设置生命周期 + candidate.setScope(scopeMetadata.getScopeName()); + // 创建beanName + String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); + if (candidate instanceof AbstractBeanDefinition) { + // 设置默认属性 具体方法:org.springframework.beans.factory.support.AbstractBeanDefinition.applyDefaults + postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); + } + if (candidate instanceof AnnotatedBeanDefinition) { + // 读取Lazy,Primary 等注解 + AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); + } + // bean的重复检查 + if (checkCandidate(beanName, candidate)) { + // 创建 BeanDefinitionHolder + BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); + // 代理对象的处理 + definitionHolder = + AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); + // 放入list中,最后返回用 + beanDefinitions.add(definitionHolder); + // 注册bean + registerBeanDefinition(definitionHolder, this.registry); + } + } + } + return beanDefinitions; + } + +``` + + + +#### org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents + +```java + public Set findCandidateComponents(String basePackage) { + // 扫描 + if (this.componentsIndex != null && indexSupportsIncludeFilters()) { + return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); + } + else { + return scanCandidateComponents(basePackage); + } + } + +``` + + + +```java + /** + * 扫描当前包路径下的资源 + * @param basePackage + * @return + */ + private Set scanCandidateComponents(String basePackage) { + Set candidates = new LinkedHashSet<>(); + try { + // 字符串拼接出一个编译后的路径 classpath:// + // 这里替换了通配符 + String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + + resolveBasePackage(basePackage) + '/' + this.resourcePattern; + // 获取资源 + Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); + // 日志级别 + boolean traceEnabled = logger.isTraceEnabled(); + boolean debugEnabled = logger.isDebugEnabled(); + for (Resource resource : resources) { + if (traceEnabled) { + logger.trace("Scanning " + resource); + } + if (resource.isReadable()) { + try { + // 获取 MetadataReader + MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); + // 判断是否是 Component + if (isCandidateComponent(metadataReader)) { + ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); + sbd.setResource(resource); + sbd.setSource(resource); + if (isCandidateComponent(sbd)) { + if (debugEnabled) { + logger.debug("Identified candidate component class: " + resource); + } + candidates.add(sbd); + } + else { + if (debugEnabled) { + logger.debug("Ignored because not a concrete top-level class: " + resource); + } + } + } + else { + if (traceEnabled) { + logger.trace("Ignored because not matching any filter: " + resource); + } + } + } + catch (Throwable ex) { + throw new BeanDefinitionStoreException( + "Failed to read candidate component class: " + resource, ex); + } + } + else { + if (traceEnabled) { + logger.trace("Ignored because not readable: " + resource); + } + } + } + } + catch (IOException ex) { + throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); + } + return candidates; + } + +``` + + + +#### org.springframework.context.annotation.ScopeMetadataResolver#resolveScopeMetadata + + + +```java + /** + * 生命周期设置 + * + * @param definition the target bean definition + * @return + */ + @Override + public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) { + ScopeMetadata metadata = new ScopeMetadata(); + // 判断是否属于 AnnotatedBeanDefinition + if (definition instanceof AnnotatedBeanDefinition) { + AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition; + AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor( + annDef.getMetadata(), this.scopeAnnotationType); + if (attributes != null) { + // 获取 value 属性值并且设置 + metadata.setScopeName(attributes.getString("value")); + // 获取 proxyMode 属性值并且设置 + ScopedProxyMode proxyMode = attributes.getEnum("proxyMode"); + if (proxyMode == ScopedProxyMode.DEFAULT) { + proxyMode = this.defaultProxyMode; + } + metadata.setScopedProxyMode(proxyMode); + } + } + return metadata; + } + + +``` + +- `org.springframework.context.annotation.AnnotationScopeMetadataResolverTests#resolveScopeMetadataShouldReadScopedProxyModeFromAnnotation`测试用例 + +```java + @Test + public void resolveScopeMetadataShouldReadScopedProxyModeFromAnnotation() { + AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(AnnotatedWithScopedProxy.class); + ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(bd); + assertNotNull("resolveScopeMetadata(..) must *never* return null.", scopeMetadata); + assertEquals("request", scopeMetadata.getScopeName()); + assertEquals(TARGET_CLASS, scopeMetadata.getScopedProxyMode()); + } + +``` + + + +#### org.springframework.beans.factory.support.BeanNameGenerator#generateBeanName + +- 创建beanName `org.springframework.context.annotation.AnnotationBeanNameGenerator#generateBeanName` + + + +```java + @Override + public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { + if (definition instanceof AnnotatedBeanDefinition) { + // 如果存在bean(value="") value存在 + String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition); + if (StringUtils.hasText(beanName)) { + // Explicit bean name found. + return beanName; + } + } + // Fallback: generate a unique default bean name. + // 创建beanName + return buildDefaultBeanName(definition, registry); + } + +``` + +```java + @Nullable + protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) { + AnnotationMetadata amd = annotatedDef.getMetadata(); + Set types = amd.getAnnotationTypes(); + String beanName = null; + for (String type : types) { + AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type); + if (attributes != null && isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) { + // 获取注解的value 属性值 + Object value = attributes.get("value"); + if (value instanceof String) { + String strVal = (String) value; + // 判断是否存在值 + if (StringUtils.hasLength(strVal)) { + if (beanName != null && !strVal.equals(beanName)) { + throw new IllegalStateException("Stereotype annotations suggest inconsistent " + + "component names: '" + beanName + "' versus '" + strVal + "'"); + } + // beanName = value属性值 + beanName = strVal; + } + } + } + } + return beanName; + } + +``` + +```java +@Service(value = "dhc") +public class DemoService { + +} +``` + + + + + + + +- `org.springframework.context.annotation.AnnotationBeanNameGenerator#buildDefaultBeanName(org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.support.BeanDefinitionRegistry)` + - `org.springframework.context.annotation.AnnotationBeanNameGenerator#buildDefaultBeanName(org.springframework.beans.factory.config.BeanDefinition)` + + + +```JAVA + protected String buildDefaultBeanName(BeanDefinition definition) { + // 获取bean class name + String beanClassName = definition.getBeanClassName(); + Assert.state(beanClassName != null, "No bean class name set"); + // 获取短类名, + String shortClassName = ClassUtils.getShortName(beanClassName); + // 第一个字母小写 + return Introspector.decapitalize(shortClassName); + } + +``` + +```JAVA +@Configuration +public class BeanConfig { + @Scope(value =ConfigurableBeanFactory.SCOPE_PROTOTYPE) + @Bean(value = "hc") + public Ubean f() { + return new Ubean(); + } +} + +``` + + + + + + + +#### org.springframework.context.annotation.ClassPathBeanDefinitionScanner#postProcessBeanDefinition + +- 这个方法没什么难点,直接是set方法 + +```java + protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) { + beanDefinition.applyDefaults(this.beanDefinitionDefaults); + if (this.autowireCandidatePatterns != null) { + beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName)); + } + } + +``` + +```java + public void applyDefaults(BeanDefinitionDefaults defaults) { + setLazyInit(defaults.isLazyInit()); + setAutowireMode(defaults.getAutowireMode()); + setDependencyCheck(defaults.getDependencyCheck()); + setInitMethodName(defaults.getInitMethodName()); + setEnforceInitMethod(false); + setDestroyMethodName(defaults.getDestroyMethodName()); + setEnforceDestroyMethod(false); + } + +``` + +#### org.springframework.context.annotation.AnnotationConfigUtils#processCommonDefinitionAnnotations(org.springframework.beans.factory.annotation.AnnotatedBeanDefinition) + +```java + public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) { + processCommonDefinitionAnnotations(abd, abd.getMetadata()); + } + +``` + +```java +static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) { + // 获取 lazy 注解 + AnnotationAttributes lazy = attributesFor(metadata, Lazy.class); + if (lazy != null) { + abd.setLazyInit(lazy.getBoolean("value")); + } else if (abd.getMetadata() != metadata) { + lazy = attributesFor(abd.getMetadata(), Lazy.class); + if (lazy != null) { + abd.setLazyInit(lazy.getBoolean("value")); + } + } + + if (metadata.isAnnotated(Primary.class.getName())) { + abd.setPrimary(true); + } + AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class); + if (dependsOn != null) { + abd.setDependsOn(dependsOn.getStringArray("value")); + } + + AnnotationAttributes role = attributesFor(metadata, Role.class); + if (role != null) { + abd.setRole(role.getNumber("value").intValue()); + } + AnnotationAttributes description = attributesFor(metadata, Description.class); + if (description != null) { + abd.setDescription(description.getString("value")); + } + } +``` + + + +- 方法思路: + 1. 获取注解的属性值 + 2. 设置注解属性 + + + + + +#### org.springframework.context.annotation.ClassPathBeanDefinitionScanner#checkCandidate + +- 重复检查 + +```java + protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException { + // 判断当前 beanName 是否在注册表中 + if (!this.registry.containsBeanDefinition(beanName)) { + return true; + } + // 从注册表中获取 + BeanDefinition existingDef = this.registry.getBeanDefinition(beanName); + // 当前的bean + BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition(); + if (originatingDef != null) { + existingDef = originatingDef; + } + if (isCompatible(beanDefinition, existingDef)) { + return false; + } + throw new ConflictingBeanDefinitionException("Annotation-specified bean name '" + beanName + + "' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, " + + "non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]"); + } + +``` + + + + + +#### org.springframework.context.annotation.AnnotationConfigUtils#applyScopedProxyMode + + + +```JAVA + static BeanDefinitionHolder applyScopedProxyMode( + ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) { + + ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode(); + if (scopedProxyMode.equals(ScopedProxyMode.NO)) { + return definition; + } + boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS); + // 创建代理对象 + return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass); + } + +``` + diff --git a/docs/Spring/clazz/Spring-自定义标签解析.md b/docs/Spring/clazz/Spring-自定义标签解析.md new file mode 100644 index 0000000..8a700f8 --- /dev/null +++ b/docs/Spring/clazz/Spring-自定义标签解析.md @@ -0,0 +1,658 @@ +# Spring 自定义标签解析 +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) +- 与自定义标签解析相关的类 + 1. `org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser` + 2. `org.springframework.beans.factory.xml.NamespaceHandlerSupport` + +- 开始源码之前先搭建一个环境 + + +## 环境搭建 +- 创建对象 +```java +public class UserXtd { + private String userName; + private String emailAddress; + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getEmailAddress() { + return emailAddress; + } + + public void setEmailAddress(String emailAddress) { + this.emailAddress = emailAddress; + } +} +``` +- 创建 xsd 文件 +```xml + + + + + + + + + + + +``` +- 创建 namespaceHandler +```java +public class UserNamespaceHandler extends NamespaceHandlerSupport { + @Override + public void init() { + registerBeanDefinitionParser("myUser", new UserBeanDefinitionParser()); + } +} +``` +- 创建 beanDefinitionParser +```java +public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { + /** + * 标签对应class + * @param element the {@code Element} that is being parsed + * @return + */ + @Override + protected Class> getBeanClass(Element element) { + return UserXtd.class; + } + + + @Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + // 获取 userName 标签属性值 + String name = element.getAttribute("userName"); + // 获取 emailAddress 标签属性值 + String address = element.getAttribute("emailAddress"); + + if (StringUtils.hasText(name)) { + builder.addPropertyValue("userName", name); + } + if (StringUtils.hasText(address)) { + builder.addPropertyValue("emailAddress", address); + } + } +} + +``` +- 创建 resource/META-INF/spring.handlers +```text +http\://www.huifer.com/schema/user=com.huifer.source.spring.parser.UserNamespaceHandler +``` +- 创建 resource/META-INF/spring.schemas +```text +http\://www.huifer.com/schema/user.xsd=META-INF/spring-test.xsd +``` +- 创建测试用例xml +```xml + + + + + + +``` +- 创建 Java 运行方法 +```java +/** + * 自定义标签测试用例 + */ +public class XSDDemo { + public static void main(String[] args) { + ApplicationContext applicationContext = new ClassPathXmlApplicationContext("XTD-xml.xml"); + UserXtd user = (UserXtd) applicationContext.getBean("testUserBean"); + System.out.println(user.getEmailAddress()); + } +} +``` +- 这里我们希望输出结果是`huifer97@163.com`,运行后结果也确实是`huifer97@163.com` + +## 解析 DefaultNamespaceHandlerResolver +- 入口方法`org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions` +```java + 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 { + // 非spring 默认标签解析 + delegate.parseCustomElement(ele); + } + } + } + } + else { + delegate.parseCustomElement(root); + } + } + +``` +- 调用链路 +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(org.w3c.dom.Element)` + - `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)` + +```java + /** + * Parse a custom element (outside of the default namespace). + * + * 自定义标签解析 + * + * @param ele the element to parse + * @param containingBd the containing bean definition (if any) + * @return the resulting bean definition + */ + @Nullable + 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)); + } + +``` + + + +- `http://www.huifer.com/schema/user`和我们定义的xsd文件中的url相同,如何找到对应的NamespaceHandler,在`META-INF/spring.handlers`中有定义, + + `http\://www.huifer.com/schema/user=com.huifer.source.spring.parser.UserNamespaceHandler` + + `NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);`这行代码就是获取`spring.handlers`中的定义 + +- 处理方法`org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve` + + + +```java + /** + * Locate the {@link NamespaceHandler} for the supplied namespace URI + * from the configured mappings. + * + * 根据 namespaceUri 获取对应的 {@link NamespaceHandler} + * @param namespaceUri the relevant namespace URI + * @return the located {@link NamespaceHandler}, or {@code null} if none found + */ + @Override + @Nullable + public NamespaceHandler resolve(String namespaceUri) { + // 获取handlerMapping + Map handlerMappings = getHandlerMappings(); + // 从 handlerMapping 中获取类名 + 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); + // 调用init()方法,自定义类中实现 + namespaceHandler.init(); + // 放入缓存 + handlerMappings.put(namespaceUri, namespaceHandler); + // 返回自定义的 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); + } + } + } + +``` + + + +- `org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#getHandlerMappings`跟踪这个方法 + +```JAVA + /** + * Load the specified NamespaceHandler mappings lazily. + * + * 获取handlerMappings + */ + private Map getHandlerMappings() { + Map handlerMappings = this.handlerMappings; + } +``` + + + + + +- 这里直接存在数据了,他是从什么时候加载的? + +- `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions` + + 这个方法在注册bean定义的时候调用 + + ```java + public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { + BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); + int countBefore = getRegistry().getBeanDefinitionCount(); + // 注册方法 + // createReaderContext 初始化HandlerMapping + documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); + return getRegistry().getBeanDefinitionCount() - countBefore; + } + + ``` + +- 继续跟踪`createReaderContext` + + ```java + org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createReaderContext + ``` + + ```java + public XmlReaderContext createReaderContext(Resource resource) { + return new XmlReaderContext(resource, this.problemReporter, this.eventListener, + this.sourceExtractor, this, getNamespaceHandlerResolver()); + } + + ``` + +- 继续跟踪`getNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#getNamespaceHandlerResolver` + + ```java + public NamespaceHandlerResolver getNamespaceHandlerResolver() { + if (this.namespaceHandlerResolver == null) { + this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver(); + } + return this.namespaceHandlerResolver; + } + + ``` + +- 继续跟踪`createDefaultNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createDefaultNamespaceHandlerResolver` + + ```java + protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() { + ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader()); + return new DefaultNamespaceHandlerResolver(cl); + } + ``` + + + +- 继续跟踪`DefaultNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver` + + ```java + public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) { + this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); + } + + ``` + + 他回到了我们之前疑问的地方 `handlerMappings` 如何出现的 + + 断点 + +  + + ```JAVA + public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) { + this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); + } + ``` + + `public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";` + +  + + 此时还是空 + + 走完 + +  + + ```java + @Override + public String toString() { + return "NamespaceHandlerResolver using mappings " + getHandlerMappings(); + } + + ``` + + + +```JAVA + /** + * Load the specified NamespaceHandler mappings lazily. + * + * 获取handlerMappings + */ + private Map getHandlerMappings() { + Map handlerMappings = this.handlerMappings; + // 缓存不存在 + if (handlerMappings == null) { + synchronized (this) { + handlerMappings = this.handlerMappings; + if (handlerMappings == null) { + if (logger.isTraceEnabled()) { + logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]"); + } + try { + // 将本地文件读出 + Properties mappings = + PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader); + if (logger.isTraceEnabled()) { + logger.trace("Loaded NamespaceHandler mappings: " + mappings); + } + handlerMappings = new ConcurrentHashMap<>(mappings.size()); + // 转换成map结构 + CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings); + this.handlerMappings = handlerMappings; + } + catch (IOException ex) { + throw new IllegalStateException( + "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex); + } + } + } + } + return handlerMappings; + } + +``` + + + + + + + + + +## org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#resolve + +```java + @Override + @Nullable + public NamespaceHandler resolve(String namespaceUri) { + // 获取handlerMapping + Map handlerMappings = getHandlerMappings(); + // 从 handlerMapping 中获取类名 + 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); + // 调用init()方法,自定义类中实现 + namespaceHandler.init(); + // 放入缓存 + handlerMappings.put(namespaceUri, namespaceHandler); + // 返回自定义的 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); + } + } + } + +``` + +执行`init`方法 + +```java +public class UserNamespaceHandler extends NamespaceHandlerSupport { + @Override + public void init() { + registerBeanDefinitionParser("myUser", new UserBeanDefinitionParser()); + } +} +``` + +```java + /** + * Subclasses can call this to register the supplied {@link BeanDefinitionParser} to + * handle the specified element. The element name is the local (non-namespace qualified) + * name. + * + * 将标签名称,标签解析类放入 + */ + protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) { + this.parsers.put(elementName, parser); + } + +``` + + + +- 方法走完,回到开始的方法 + + ```java + /** + * Parse a custom element (outside of the default namespace). + * + * 自定义标签解析 + * + * @param ele the element to parse + * @param containingBd the containing bean definition (if any) + * @return the resulting bean definition + */ + @Nullable + public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { + // 自定义标签解析 + String namespaceUri = getNamespaceURI(ele); + if (namespaceUri == null) { + return null; + } + // 根据命名空间获取处理类 + // org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve + 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)); + } + + ``` + + + + + + + + + +## org.springframework.beans.factory.xml.NamespaceHandler#parse + +- `org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse` + + ```java + @Override + @Nullable + public BeanDefinition parse(Element element, ParserContext parserContext) { + BeanDefinitionParser parser = findParserForElement(element, parserContext); + return (parser != null ? parser.parse(element, parserContext) : null); + } + + ``` + +### org.springframework.beans.factory.xml.NamespaceHandlerSupport#findParserForElement + +```java + @Nullable + private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { + // 获取标签名称 + String localName = parserContext.getDelegate().getLocalName(element); + // 在map中获取对应的标签解析类 + BeanDefinitionParser parser = this.parsers.get(localName); + // 空报错 + if (parser == null) { + parserContext.getReaderContext().fatal( + "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); + } + // 不为空返回 + return parser; + } + +``` + + + +### org.springframework.beans.factory.xml.BeanDefinitionParser#parse + +- `org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parse` + +```java + public final BeanDefinition parse(Element element, ParserContext parserContext) { + /** + * {@link AbstractSingleBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)} + */ + AbstractBeanDefinition definition = parseInternal(element, parserContext); + + + } +``` + +### org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#parseInternal + +```java +@Override + protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); + String parentName = getParentName(element); + if (parentName != null) { + builder.getRawBeanDefinition().setParentName(parentName); + } + // 调用自己实现的方法 com.huifer.source.spring.parser.UserBeanDefinitionParser.getBeanClass + Class> beanClass = getBeanClass(element); + if (beanClass != null) { + builder.getRawBeanDefinition().setBeanClass(beanClass); + } + else { + // getBeanClassName 同样也是可以在自定义的解析类中实现 + 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. + // 设置scope + builder.setScope(containingBd.getScope()); + } + if (parserContext.isDefaultLazyInit()) { + // Default-lazy-init applies to custom bean definitions as well. + // 设置 lazy-init + builder.setLazyInit(true); + } + + // 执行解析方法,在自定义解析类中存在com.huifer.source.spring.parser.UserBeanDefinitionParser.doParse + doParse(element, parserContext, builder); + return builder.getBeanDefinition(); + } +``` + + + + + +执行`com.huifer.source.spring.parser.UserBeanDefinitionParser#doParse` + +```JAVA +@Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + // 获取 userName 标签属性值 + String name = element.getAttribute("userName"); + // 获取 emailAddress 标签属性值 + String address = element.getAttribute("emailAddress"); + + if (StringUtils.hasText(name)) { + builder.addPropertyValue("userName", name); + } + if (StringUtils.hasText(address)) { + builder.addPropertyValue("emailAddress", address); + } + } +``` + + + + + diff --git a/images/spring/image-20200109084131415.png b/images/spring/image-20200109084131415.png new file mode 100644 index 0000000..6d99aa1 Binary files /dev/null and b/images/spring/image-20200109084131415.png differ diff --git a/images/spring/image-20200109085606240.png b/images/spring/image-20200109085606240.png new file mode 100644 index 0000000..61883bf Binary files /dev/null and b/images/spring/image-20200109085606240.png differ diff --git a/images/spring/image-20200109090456547.png b/images/spring/image-20200109090456547.png new file mode 100644 index 0000000..19e745c Binary files /dev/null and b/images/spring/image-20200109090456547.png differ diff --git a/images/spring/image-20200109090655157.png b/images/spring/image-20200109090655157.png new file mode 100644 index 0000000..97c431c Binary files /dev/null and b/images/spring/image-20200109090655157.png differ diff --git a/images/spring/image-20200109091216505.png b/images/spring/image-20200109091216505.png new file mode 100644 index 0000000..cbc2d48 Binary files /dev/null and b/images/spring/image-20200109091216505.png differ diff --git a/images/spring/image-20200109092801572.png b/images/spring/image-20200109092801572.png new file mode 100644 index 0000000..043a9ca Binary files /dev/null and b/images/spring/image-20200109092801572.png differ diff --git a/images/spring/image-20200109093242494.png b/images/spring/image-20200109093242494.png new file mode 100644 index 0000000..8d8077f Binary files /dev/null and b/images/spring/image-20200109093242494.png differ diff --git a/images/spring/image-20200109094032421.png b/images/spring/image-20200109094032421.png new file mode 100644 index 0000000..a8dcfb1 Binary files /dev/null and b/images/spring/image-20200109094032421.png differ diff --git a/images/spring/image-20200109094649217.png b/images/spring/image-20200109094649217.png new file mode 100644 index 0000000..2c2b1f2 Binary files /dev/null and b/images/spring/image-20200109094649217.png differ diff --git a/images/spring/image-20200109094654409.png b/images/spring/image-20200109094654409.png new file mode 100644 index 0000000..2c2b1f2 Binary files /dev/null and b/images/spring/image-20200109094654409.png differ diff --git a/images/spring/image-20200109150841916.png b/images/spring/image-20200109150841916.png new file mode 100644 index 0000000..c85d445 Binary files /dev/null and b/images/spring/image-20200109150841916.png differ diff --git a/images/spring/image-20200110093044672.png b/images/spring/image-20200110093044672.png new file mode 100644 index 0000000..514b59c Binary files /dev/null and b/images/spring/image-20200110093044672.png differ diff --git a/images/spring/image-20200115083744268.png b/images/spring/image-20200115083744268.png new file mode 100644 index 0000000..8a465cd Binary files /dev/null and b/images/spring/image-20200115083744268.png differ diff --git a/images/spring/image-20200115084031725.png b/images/spring/image-20200115084031725.png new file mode 100644 index 0000000..6742458 Binary files /dev/null and b/images/spring/image-20200115084031725.png differ diff --git a/images/spring/image-20200115093602651.png b/images/spring/image-20200115093602651.png new file mode 100644 index 0000000..fa04a3c Binary files /dev/null and b/images/spring/image-20200115093602651.png differ diff --git a/images/spring/image-20200115105941265.png b/images/spring/image-20200115105941265.png new file mode 100644 index 0000000..88c456b Binary files /dev/null and b/images/spring/image-20200115105941265.png differ diff --git a/images/spring/image-20200115141708702.png b/images/spring/image-20200115141708702.png new file mode 100644 index 0000000..2c1ada0 Binary files /dev/null and b/images/spring/image-20200115141708702.png differ diff --git a/images/spring/image-20200115143315633.png b/images/spring/image-20200115143315633.png new file mode 100644 index 0000000..6edee36 Binary files /dev/null and b/images/spring/image-20200115143315633.png differ diff --git a/images/spring/image-20200115143456554.png b/images/spring/image-20200115143456554.png new file mode 100644 index 0000000..d19ba94 Binary files /dev/null and b/images/spring/image-20200115143456554.png differ diff --git a/images/spring/image-20200116085344737.png b/images/spring/image-20200116085344737.png new file mode 100644 index 0000000..6f39a30 Binary files /dev/null and b/images/spring/image-20200116085344737.png differ diff --git a/images/spring/image-20200116085423073.png b/images/spring/image-20200116085423073.png new file mode 100644 index 0000000..c40cad2 Binary files /dev/null and b/images/spring/image-20200116085423073.png differ diff --git a/images/spring/image-20200116085726577.png b/images/spring/image-20200116085726577.png new file mode 100644 index 0000000..31a3481 Binary files /dev/null and b/images/spring/image-20200116085726577.png differ diff --git a/images/spring/image-20200116085737632.png b/images/spring/image-20200116085737632.png new file mode 100644 index 0000000..ae8f4cb Binary files /dev/null and b/images/spring/image-20200116085737632.png differ diff --git a/images/spring/image-20200116085927359.png b/images/spring/image-20200116085927359.png new file mode 100644 index 0000000..7a02538 Binary files /dev/null and b/images/spring/image-20200116085927359.png differ diff --git a/images/spring/image-20200116092259944.png b/images/spring/image-20200116092259944.png new file mode 100644 index 0000000..0d20a5a Binary files /dev/null and b/images/spring/image-20200116092259944.png differ diff --git a/images/spring/image-20200116141838601.png b/images/spring/image-20200116141838601.png new file mode 100644 index 0000000..e4ee61b Binary files /dev/null and b/images/spring/image-20200116141838601.png differ diff --git a/images/spring/image-20200116141932486.png b/images/spring/image-20200116141932486.png new file mode 100644 index 0000000..8e06086 Binary files /dev/null and b/images/spring/image-20200116141932486.png differ diff --git a/images/spring/image-20200119085346675.png b/images/spring/image-20200119085346675.png new file mode 100644 index 0000000..2c23ebb Binary files /dev/null and b/images/spring/image-20200119085346675.png differ diff --git a/images/spring/image-20200119085655734.png b/images/spring/image-20200119085655734.png new file mode 100644 index 0000000..18bf79e Binary files /dev/null and b/images/spring/image-20200119085655734.png differ diff --git a/images/spring/image-20200119101017989.png b/images/spring/image-20200119101017989.png new file mode 100644 index 0000000..c8b3ad9 Binary files /dev/null and b/images/spring/image-20200119101017989.png differ diff --git a/images/spring/image-20200119101026726.png b/images/spring/image-20200119101026726.png new file mode 100644 index 0000000..14b6c3e Binary files /dev/null and b/images/spring/image-20200119101026726.png differ diff --git a/images/spring/image-20200119101107820.png b/images/spring/image-20200119101107820.png new file mode 100644 index 0000000..e2546cb Binary files /dev/null and b/images/spring/image-20200119101107820.png differ diff --git a/images/spring/image-20200119101516591.png b/images/spring/image-20200119101516591.png new file mode 100644 index 0000000..4236551 Binary files /dev/null and b/images/spring/image-20200119101516591.png differ
To be called for eager registration of singletons. + *
+ * 添加单例对象的操作方法 + * + * @param beanName the name of the bean + * @param singletonObject the singleton object + */ + protected void addSingleton(String beanName, Object singletonObject) { + synchronized (this.singletonObjects) { + this.singletonObjects.put(beanName, singletonObject); + this.singletonFactories.remove(beanName); + this.earlySingletonObjects.remove(beanName); + this.registeredSingletons.add(beanName); + } + } +``` +- 这些变量是什么 +```java + /** + * 单例对象的缓存: beanName -> Object + */ + private final Map singletonObjects = new ConcurrentHashMap<>(256); + + /** + * 单例工厂的缓存: beanName -> ObjectFactory。 + */ + private final Map> singletonFactories = new HashMap<>(16); + + /** + * 延迟加载的单例对象缓存: beanName -> Object + */ + private final Map earlySingletonObjects = new HashMap<>(16); + + /** + * 已经注册过的单例对象名称(beanName) + */ + private final Set registeredSingletons = new LinkedHashSet<>(256); + + /** + * 当前正在创建的单例对象名称(beanName) + */ + private final Set singletonsCurrentlyInCreation = + Collections.newSetFromMap(new ConcurrentHashMap<>(16)); + + private final Set inCreationCheckExclusions = + Collections.newSetFromMap(new ConcurrentHashMap<>(16)); + /** + * 摧毁单例对象 + */ + private final Map disposableBeans = new LinkedHashMap<>(); + private final Map> containedBeanMap = new ConcurrentHashMap<>(16); + /** + * bean 和beanName的关系 + */ + private final Map> dependentBeanMap = new ConcurrentHashMap<>(64); + /** + * bean 依赖关系 beanName -> 依赖关系 + */ + private final Map> dependenciesForBeanMap = new ConcurrentHashMap<>(64); + /** + * 异常列表 + */ + @Nullable + private Set suppressedExceptions; + /** + * 标记是否在 destroySingletons 上 + */ + private boolean singletonsCurrentlyInDestruction = false; + +``` + +- 注册方法至此结束 + +## 获取方法解析 +- `org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(java.lang.String)` +```java + @Override + @Nullable + public Object getSingleton(String beanName) { + return getSingleton(beanName, true); + } +``` + +```java + @Nullable + protected Object getSingleton(String beanName, boolean allowEarlyReference) { + // 从列表中获取单例对象 + Object singletonObject = this.singletonObjects.get(beanName); + // 判断当前beanName是否存在 + if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { + synchronized (this.singletonObjects) { + // 从延迟加载中获取 + singletonObject = this.earlySingletonObjects.get(beanName); + if (singletonObject == null && allowEarlyReference) { + // 从singletonFactories获取ObjectFactory + ObjectFactory> singletonFactory = this.singletonFactories.get(beanName); + if (singletonFactory != null) { + // 获取对象 + singletonObject = singletonFactory.getObject(); + // 加入缓存 + this.earlySingletonObjects.put(beanName, singletonObject); + this.singletonFactories.remove(beanName); + } + } + } + } + return singletonObject; + } + +``` + +- 获取单例对象的本质就是从map中获取 ObjectFactory 进而执行 getObject() +`ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);` +- 测试方法 +```java + + TestBean tb2 = (TestBean) beanRegistry.getSingleton("tb2", new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return new TestBean(); + } + }); +``` + +- 获取单例对象的方式 + +```java +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; + } + } +``` + +不难发现最后都是通过`singletonObject = singletonFactory.getObject();`进行获取 + +这个地方的方法实际上就是测试类中的 + +```java +new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return new TestBean(); + } + } +``` + +通过`getObject`就可以获取当前对象 \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-OrderComparator.md b/docs/Spring/clazz/Spring-OrderComparator.md new file mode 100644 index 0000000..173f546 --- /dev/null +++ b/docs/Spring/clazz/Spring-OrderComparator.md @@ -0,0 +1,98 @@ +# Spring OrderComparator +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) + + +```java + private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) { + boolean p1 = (o1 instanceof PriorityOrdered); + boolean p2 = (o2 instanceof PriorityOrdered); + if (p1 && !p2) { + return -1; + } else if (p2 && !p1) { + return 1; + } + + int i1 = getOrder(o1, sourceProvider); + int i2 = getOrder(o2, sourceProvider); + // 对比两个Order值得大小返回 + return Integer.compare(i1, i2); + } + +``` + +```java + private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) { + Integer order = null; + if (obj != null && sourceProvider != null) { + // 获取Order + Object orderSource = sourceProvider.getOrderSource(obj); + if (orderSource != null) { + if (orderSource.getClass().isArray()) { + // 获取 OrderSourceProvider 的值 + Object[] sources = ObjectUtils.toObjectArray(orderSource); + for (Object source : sources) { + // 找 order 返回 + order = findOrder(source); + if (order != null) { + break; + } + } + } else { + // 寻找 order + order = findOrder(orderSource); + } + } + } + return (order != null ? order : getOrder(obj)); + } + +``` + +- 测试用例 +```java + @Test + public void compareWithSourceProviderArray() { + Comparator customComparator = this.comparator.withSourceProvider( + new TestSourceProvider(5L, new Object[]{new StubOrdered(10), new StubOrdered(-25)})); + assertEquals(-1, customComparator.compare(5L, new Object())); + } + +``` + + + + + +```java + @Nullable + protected Integer findOrder(Object obj) { + // 获取Ordered实现类 + return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null); + } + +``` + +```java + private static final class StubOrdered implements Ordered { + + private final int order; + + + public StubOrdered(int order) { + this.order = order; + } + + @Override + public int getOrder() { + return this.order; + } + } + +``` + + + + + +最终`Integer.compare(i1, i2)`比较返回 OK ! \ No newline at end of file diff --git a/docs/Spring/clazz/Spring-scan.md b/docs/Spring/clazz/Spring-scan.md new file mode 100644 index 0000000..5e03fe9 --- /dev/null +++ b/docs/Spring/clazz/Spring-scan.md @@ -0,0 +1,534 @@ +# Spring scan +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) + +## 解析 +- Spring 注解形式使用有下面两种方式 + 1. 通过`AnnotationConfigApplicationContext`参数:扫描包 + 2. 通过xml配置`context:component-scan`属性`base-package` +```java + AnnotationConfigApplicationContext aac = + new AnnotationConfigApplicationContext("com.huifer.source.spring.ann"); +``` +```xml + + +``` + +- 目标明确开始找入口方法 +- `AnnotationConfigApplicationContext`直接点进去看就找到了 +```java +public AnnotationConfigApplicationContext(String... basePackages) { + this(); + // 扫描包 + scan(basePackages); + refresh(); + } +``` +- `context:component-scan`寻找方式:冒号`:`钱+NamespaceHandler 或者全文搜索`component-scan`,最终找到`org.springframework.context.config.ContextNamespaceHandler` +```java +public class ContextNamespaceHandler extends NamespaceHandlerSupport { + + @Override + public void init() { + registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); + registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); + registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); + registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); + registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser()); + registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); + registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser()); + registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser()); + } + +} +``` + +### org.springframework.context.annotation.ComponentScanBeanDefinitionParser + + + +- 实现`BeanDefinitionParser`直接看`parse`方法 +```java + @Override + @Nullable + public BeanDefinition parse(Element element, ParserContext parserContext) { + // 获取 base-package 属性值 + String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); + // 处理 ${} + basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); + // 分隔符`,;\t\n`切分 + String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, + ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); + + // Actually scan for bean definitions and register them. + // 扫描对象创建 + ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); + // 执行扫描方法 + Set beanDefinitions = scanner.doScan(basePackages); + // 注册组件,触发监听 + registerComponents(parserContext.getReaderContext(), beanDefinitions, element); + + return null; + } + +``` + +- 回过头看`AnnotationConfigApplicationContext` +### org.springframework.context.annotation.AnnotationConfigApplicationContext +```java +public AnnotationConfigApplicationContext(String... basePackages) { + this(); + // 扫描包 + scan(basePackages); + refresh(); + } +``` +```java + private final ClassPathBeanDefinitionScanner scanner; + + @Override + public void scan(String... basePackages) { + Assert.notEmpty(basePackages, "At least one base package must be specified"); + this.scanner.scan(basePackages); + } + +``` +- `org.springframework.context.annotation.ClassPathBeanDefinitionScanner.scan` +```java +public int scan(String... basePackages) { + + // 获取bean数量 + 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); + } +``` + +- 这个地方`doScan`似曾相识,他就是`org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse`中的`doScan`,下一步解析doScan + +### org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan + + + +```java + protected Set doScan(String... basePackages) { + Assert.notEmpty(basePackages, "At least one base package must be specified"); + Set beanDefinitions = new LinkedHashSet<>(); + for (String basePackage : basePackages) { + // 寻找组件 + Set candidates = findCandidateComponents(basePackage); + for (BeanDefinition candidate : candidates) { + // bean 作用域设置 + ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); + // 设置生命周期 + candidate.setScope(scopeMetadata.getScopeName()); + // 创建beanName + String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); + if (candidate instanceof AbstractBeanDefinition) { + // 设置默认属性 具体方法:org.springframework.beans.factory.support.AbstractBeanDefinition.applyDefaults + postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); + } + if (candidate instanceof AnnotatedBeanDefinition) { + // 读取Lazy,Primary 等注解 + AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); + } + // bean的重复检查 + if (checkCandidate(beanName, candidate)) { + // 创建 BeanDefinitionHolder + BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); + // 代理对象的处理 + definitionHolder = + AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); + // 放入list中,最后返回用 + beanDefinitions.add(definitionHolder); + // 注册bean + registerBeanDefinition(definitionHolder, this.registry); + } + } + } + return beanDefinitions; + } + +``` + + + +#### org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents + +```java + public Set findCandidateComponents(String basePackage) { + // 扫描 + if (this.componentsIndex != null && indexSupportsIncludeFilters()) { + return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); + } + else { + return scanCandidateComponents(basePackage); + } + } + +``` + + + +```java + /** + * 扫描当前包路径下的资源 + * @param basePackage + * @return + */ + private Set scanCandidateComponents(String basePackage) { + Set candidates = new LinkedHashSet<>(); + try { + // 字符串拼接出一个编译后的路径 classpath:// + // 这里替换了通配符 + String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + + resolveBasePackage(basePackage) + '/' + this.resourcePattern; + // 获取资源 + Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); + // 日志级别 + boolean traceEnabled = logger.isTraceEnabled(); + boolean debugEnabled = logger.isDebugEnabled(); + for (Resource resource : resources) { + if (traceEnabled) { + logger.trace("Scanning " + resource); + } + if (resource.isReadable()) { + try { + // 获取 MetadataReader + MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); + // 判断是否是 Component + if (isCandidateComponent(metadataReader)) { + ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); + sbd.setResource(resource); + sbd.setSource(resource); + if (isCandidateComponent(sbd)) { + if (debugEnabled) { + logger.debug("Identified candidate component class: " + resource); + } + candidates.add(sbd); + } + else { + if (debugEnabled) { + logger.debug("Ignored because not a concrete top-level class: " + resource); + } + } + } + else { + if (traceEnabled) { + logger.trace("Ignored because not matching any filter: " + resource); + } + } + } + catch (Throwable ex) { + throw new BeanDefinitionStoreException( + "Failed to read candidate component class: " + resource, ex); + } + } + else { + if (traceEnabled) { + logger.trace("Ignored because not readable: " + resource); + } + } + } + } + catch (IOException ex) { + throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); + } + return candidates; + } + +``` + + + +#### org.springframework.context.annotation.ScopeMetadataResolver#resolveScopeMetadata + + + +```java + /** + * 生命周期设置 + * + * @param definition the target bean definition + * @return + */ + @Override + public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) { + ScopeMetadata metadata = new ScopeMetadata(); + // 判断是否属于 AnnotatedBeanDefinition + if (definition instanceof AnnotatedBeanDefinition) { + AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition; + AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor( + annDef.getMetadata(), this.scopeAnnotationType); + if (attributes != null) { + // 获取 value 属性值并且设置 + metadata.setScopeName(attributes.getString("value")); + // 获取 proxyMode 属性值并且设置 + ScopedProxyMode proxyMode = attributes.getEnum("proxyMode"); + if (proxyMode == ScopedProxyMode.DEFAULT) { + proxyMode = this.defaultProxyMode; + } + metadata.setScopedProxyMode(proxyMode); + } + } + return metadata; + } + + +``` + +- `org.springframework.context.annotation.AnnotationScopeMetadataResolverTests#resolveScopeMetadataShouldReadScopedProxyModeFromAnnotation`测试用例 + +```java + @Test + public void resolveScopeMetadataShouldReadScopedProxyModeFromAnnotation() { + AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(AnnotatedWithScopedProxy.class); + ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(bd); + assertNotNull("resolveScopeMetadata(..) must *never* return null.", scopeMetadata); + assertEquals("request", scopeMetadata.getScopeName()); + assertEquals(TARGET_CLASS, scopeMetadata.getScopedProxyMode()); + } + +``` + + + +#### org.springframework.beans.factory.support.BeanNameGenerator#generateBeanName + +- 创建beanName `org.springframework.context.annotation.AnnotationBeanNameGenerator#generateBeanName` + + + +```java + @Override + public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { + if (definition instanceof AnnotatedBeanDefinition) { + // 如果存在bean(value="") value存在 + String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition); + if (StringUtils.hasText(beanName)) { + // Explicit bean name found. + return beanName; + } + } + // Fallback: generate a unique default bean name. + // 创建beanName + return buildDefaultBeanName(definition, registry); + } + +``` + +```java + @Nullable + protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) { + AnnotationMetadata amd = annotatedDef.getMetadata(); + Set types = amd.getAnnotationTypes(); + String beanName = null; + for (String type : types) { + AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type); + if (attributes != null && isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) { + // 获取注解的value 属性值 + Object value = attributes.get("value"); + if (value instanceof String) { + String strVal = (String) value; + // 判断是否存在值 + if (StringUtils.hasLength(strVal)) { + if (beanName != null && !strVal.equals(beanName)) { + throw new IllegalStateException("Stereotype annotations suggest inconsistent " + + "component names: '" + beanName + "' versus '" + strVal + "'"); + } + // beanName = value属性值 + beanName = strVal; + } + } + } + } + return beanName; + } + +``` + +```java +@Service(value = "dhc") +public class DemoService { + +} +``` + + + + + + + +- `org.springframework.context.annotation.AnnotationBeanNameGenerator#buildDefaultBeanName(org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.support.BeanDefinitionRegistry)` + - `org.springframework.context.annotation.AnnotationBeanNameGenerator#buildDefaultBeanName(org.springframework.beans.factory.config.BeanDefinition)` + + + +```JAVA + protected String buildDefaultBeanName(BeanDefinition definition) { + // 获取bean class name + String beanClassName = definition.getBeanClassName(); + Assert.state(beanClassName != null, "No bean class name set"); + // 获取短类名, + String shortClassName = ClassUtils.getShortName(beanClassName); + // 第一个字母小写 + return Introspector.decapitalize(shortClassName); + } + +``` + +```JAVA +@Configuration +public class BeanConfig { + @Scope(value =ConfigurableBeanFactory.SCOPE_PROTOTYPE) + @Bean(value = "hc") + public Ubean f() { + return new Ubean(); + } +} + +``` + + + + + + + +#### org.springframework.context.annotation.ClassPathBeanDefinitionScanner#postProcessBeanDefinition + +- 这个方法没什么难点,直接是set方法 + +```java + protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) { + beanDefinition.applyDefaults(this.beanDefinitionDefaults); + if (this.autowireCandidatePatterns != null) { + beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName)); + } + } + +``` + +```java + public void applyDefaults(BeanDefinitionDefaults defaults) { + setLazyInit(defaults.isLazyInit()); + setAutowireMode(defaults.getAutowireMode()); + setDependencyCheck(defaults.getDependencyCheck()); + setInitMethodName(defaults.getInitMethodName()); + setEnforceInitMethod(false); + setDestroyMethodName(defaults.getDestroyMethodName()); + setEnforceDestroyMethod(false); + } + +``` + +#### org.springframework.context.annotation.AnnotationConfigUtils#processCommonDefinitionAnnotations(org.springframework.beans.factory.annotation.AnnotatedBeanDefinition) + +```java + public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) { + processCommonDefinitionAnnotations(abd, abd.getMetadata()); + } + +``` + +```java +static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) { + // 获取 lazy 注解 + AnnotationAttributes lazy = attributesFor(metadata, Lazy.class); + if (lazy != null) { + abd.setLazyInit(lazy.getBoolean("value")); + } else if (abd.getMetadata() != metadata) { + lazy = attributesFor(abd.getMetadata(), Lazy.class); + if (lazy != null) { + abd.setLazyInit(lazy.getBoolean("value")); + } + } + + if (metadata.isAnnotated(Primary.class.getName())) { + abd.setPrimary(true); + } + AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class); + if (dependsOn != null) { + abd.setDependsOn(dependsOn.getStringArray("value")); + } + + AnnotationAttributes role = attributesFor(metadata, Role.class); + if (role != null) { + abd.setRole(role.getNumber("value").intValue()); + } + AnnotationAttributes description = attributesFor(metadata, Description.class); + if (description != null) { + abd.setDescription(description.getString("value")); + } + } +``` + + + +- 方法思路: + 1. 获取注解的属性值 + 2. 设置注解属性 + + + + + +#### org.springframework.context.annotation.ClassPathBeanDefinitionScanner#checkCandidate + +- 重复检查 + +```java + protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException { + // 判断当前 beanName 是否在注册表中 + if (!this.registry.containsBeanDefinition(beanName)) { + return true; + } + // 从注册表中获取 + BeanDefinition existingDef = this.registry.getBeanDefinition(beanName); + // 当前的bean + BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition(); + if (originatingDef != null) { + existingDef = originatingDef; + } + if (isCompatible(beanDefinition, existingDef)) { + return false; + } + throw new ConflictingBeanDefinitionException("Annotation-specified bean name '" + beanName + + "' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, " + + "non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]"); + } + +``` + + + + + +#### org.springframework.context.annotation.AnnotationConfigUtils#applyScopedProxyMode + + + +```JAVA + static BeanDefinitionHolder applyScopedProxyMode( + ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) { + + ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode(); + if (scopedProxyMode.equals(ScopedProxyMode.NO)) { + return definition; + } + boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS); + // 创建代理对象 + return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass); + } + +``` + diff --git a/docs/Spring/clazz/Spring-自定义标签解析.md b/docs/Spring/clazz/Spring-自定义标签解析.md new file mode 100644 index 0000000..8a700f8 --- /dev/null +++ b/docs/Spring/clazz/Spring-自定义标签解析.md @@ -0,0 +1,658 @@ +# Spring 自定义标签解析 +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [huifer-spring](https://github.com/huifer/spring-framework-read) +- 与自定义标签解析相关的类 + 1. `org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser` + 2. `org.springframework.beans.factory.xml.NamespaceHandlerSupport` + +- 开始源码之前先搭建一个环境 + + +## 环境搭建 +- 创建对象 +```java +public class UserXtd { + private String userName; + private String emailAddress; + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getEmailAddress() { + return emailAddress; + } + + public void setEmailAddress(String emailAddress) { + this.emailAddress = emailAddress; + } +} +``` +- 创建 xsd 文件 +```xml + + + + + + + + + + + +``` +- 创建 namespaceHandler +```java +public class UserNamespaceHandler extends NamespaceHandlerSupport { + @Override + public void init() { + registerBeanDefinitionParser("myUser", new UserBeanDefinitionParser()); + } +} +``` +- 创建 beanDefinitionParser +```java +public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { + /** + * 标签对应class + * @param element the {@code Element} that is being parsed + * @return + */ + @Override + protected Class> getBeanClass(Element element) { + return UserXtd.class; + } + + + @Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + // 获取 userName 标签属性值 + String name = element.getAttribute("userName"); + // 获取 emailAddress 标签属性值 + String address = element.getAttribute("emailAddress"); + + if (StringUtils.hasText(name)) { + builder.addPropertyValue("userName", name); + } + if (StringUtils.hasText(address)) { + builder.addPropertyValue("emailAddress", address); + } + } +} + +``` +- 创建 resource/META-INF/spring.handlers +```text +http\://www.huifer.com/schema/user=com.huifer.source.spring.parser.UserNamespaceHandler +``` +- 创建 resource/META-INF/spring.schemas +```text +http\://www.huifer.com/schema/user.xsd=META-INF/spring-test.xsd +``` +- 创建测试用例xml +```xml + + + + + + +``` +- 创建 Java 运行方法 +```java +/** + * 自定义标签测试用例 + */ +public class XSDDemo { + public static void main(String[] args) { + ApplicationContext applicationContext = new ClassPathXmlApplicationContext("XTD-xml.xml"); + UserXtd user = (UserXtd) applicationContext.getBean("testUserBean"); + System.out.println(user.getEmailAddress()); + } +} +``` +- 这里我们希望输出结果是`huifer97@163.com`,运行后结果也确实是`huifer97@163.com` + +## 解析 DefaultNamespaceHandlerResolver +- 入口方法`org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions` +```java + 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 { + // 非spring 默认标签解析 + delegate.parseCustomElement(ele); + } + } + } + } + else { + delegate.parseCustomElement(root); + } + } + +``` +- 调用链路 +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(org.w3c.dom.Element)` + - `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)` + +```java + /** + * Parse a custom element (outside of the default namespace). + * + * 自定义标签解析 + * + * @param ele the element to parse + * @param containingBd the containing bean definition (if any) + * @return the resulting bean definition + */ + @Nullable + 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)); + } + +``` + + + +- `http://www.huifer.com/schema/user`和我们定义的xsd文件中的url相同,如何找到对应的NamespaceHandler,在`META-INF/spring.handlers`中有定义, + + `http\://www.huifer.com/schema/user=com.huifer.source.spring.parser.UserNamespaceHandler` + + `NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);`这行代码就是获取`spring.handlers`中的定义 + +- 处理方法`org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve` + + + +```java + /** + * Locate the {@link NamespaceHandler} for the supplied namespace URI + * from the configured mappings. + * + * 根据 namespaceUri 获取对应的 {@link NamespaceHandler} + * @param namespaceUri the relevant namespace URI + * @return the located {@link NamespaceHandler}, or {@code null} if none found + */ + @Override + @Nullable + public NamespaceHandler resolve(String namespaceUri) { + // 获取handlerMapping + Map handlerMappings = getHandlerMappings(); + // 从 handlerMapping 中获取类名 + 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); + // 调用init()方法,自定义类中实现 + namespaceHandler.init(); + // 放入缓存 + handlerMappings.put(namespaceUri, namespaceHandler); + // 返回自定义的 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); + } + } + } + +``` + + + +- `org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#getHandlerMappings`跟踪这个方法 + +```JAVA + /** + * Load the specified NamespaceHandler mappings lazily. + * + * 获取handlerMappings + */ + private Map getHandlerMappings() { + Map handlerMappings = this.handlerMappings; + } +``` + + + + + +- 这里直接存在数据了,他是从什么时候加载的? + +- `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions` + + 这个方法在注册bean定义的时候调用 + + ```java + public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { + BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); + int countBefore = getRegistry().getBeanDefinitionCount(); + // 注册方法 + // createReaderContext 初始化HandlerMapping + documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); + return getRegistry().getBeanDefinitionCount() - countBefore; + } + + ``` + +- 继续跟踪`createReaderContext` + + ```java + org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createReaderContext + ``` + + ```java + public XmlReaderContext createReaderContext(Resource resource) { + return new XmlReaderContext(resource, this.problemReporter, this.eventListener, + this.sourceExtractor, this, getNamespaceHandlerResolver()); + } + + ``` + +- 继续跟踪`getNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#getNamespaceHandlerResolver` + + ```java + public NamespaceHandlerResolver getNamespaceHandlerResolver() { + if (this.namespaceHandlerResolver == null) { + this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver(); + } + return this.namespaceHandlerResolver; + } + + ``` + +- 继续跟踪`createDefaultNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createDefaultNamespaceHandlerResolver` + + ```java + protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() { + ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader()); + return new DefaultNamespaceHandlerResolver(cl); + } + ``` + + + +- 继续跟踪`DefaultNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver` + + ```java + public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) { + this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); + } + + ``` + + 他回到了我们之前疑问的地方 `handlerMappings` 如何出现的 + + 断点 + +  + + ```JAVA + public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) { + this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); + } + ``` + + `public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";` + +  + + 此时还是空 + + 走完 + +  + + ```java + @Override + public String toString() { + return "NamespaceHandlerResolver using mappings " + getHandlerMappings(); + } + + ``` + + + +```JAVA + /** + * Load the specified NamespaceHandler mappings lazily. + * + * 获取handlerMappings + */ + private Map getHandlerMappings() { + Map handlerMappings = this.handlerMappings; + // 缓存不存在 + if (handlerMappings == null) { + synchronized (this) { + handlerMappings = this.handlerMappings; + if (handlerMappings == null) { + if (logger.isTraceEnabled()) { + logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]"); + } + try { + // 将本地文件读出 + Properties mappings = + PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader); + if (logger.isTraceEnabled()) { + logger.trace("Loaded NamespaceHandler mappings: " + mappings); + } + handlerMappings = new ConcurrentHashMap<>(mappings.size()); + // 转换成map结构 + CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings); + this.handlerMappings = handlerMappings; + } + catch (IOException ex) { + throw new IllegalStateException( + "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex); + } + } + } + } + return handlerMappings; + } + +``` + + + + + + + + + +## org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#resolve + +```java + @Override + @Nullable + public NamespaceHandler resolve(String namespaceUri) { + // 获取handlerMapping + Map handlerMappings = getHandlerMappings(); + // 从 handlerMapping 中获取类名 + 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); + // 调用init()方法,自定义类中实现 + namespaceHandler.init(); + // 放入缓存 + handlerMappings.put(namespaceUri, namespaceHandler); + // 返回自定义的 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); + } + } + } + +``` + +执行`init`方法 + +```java +public class UserNamespaceHandler extends NamespaceHandlerSupport { + @Override + public void init() { + registerBeanDefinitionParser("myUser", new UserBeanDefinitionParser()); + } +} +``` + +```java + /** + * Subclasses can call this to register the supplied {@link BeanDefinitionParser} to + * handle the specified element. The element name is the local (non-namespace qualified) + * name. + * + * 将标签名称,标签解析类放入 + */ + protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) { + this.parsers.put(elementName, parser); + } + +``` + + + +- 方法走完,回到开始的方法 + + ```java + /** + * Parse a custom element (outside of the default namespace). + * + * 自定义标签解析 + * + * @param ele the element to parse + * @param containingBd the containing bean definition (if any) + * @return the resulting bean definition + */ + @Nullable + public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { + // 自定义标签解析 + String namespaceUri = getNamespaceURI(ele); + if (namespaceUri == null) { + return null; + } + // 根据命名空间获取处理类 + // org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve + 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)); + } + + ``` + + + + + + + + + +## org.springframework.beans.factory.xml.NamespaceHandler#parse + +- `org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse` + + ```java + @Override + @Nullable + public BeanDefinition parse(Element element, ParserContext parserContext) { + BeanDefinitionParser parser = findParserForElement(element, parserContext); + return (parser != null ? parser.parse(element, parserContext) : null); + } + + ``` + +### org.springframework.beans.factory.xml.NamespaceHandlerSupport#findParserForElement + +```java + @Nullable + private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { + // 获取标签名称 + String localName = parserContext.getDelegate().getLocalName(element); + // 在map中获取对应的标签解析类 + BeanDefinitionParser parser = this.parsers.get(localName); + // 空报错 + if (parser == null) { + parserContext.getReaderContext().fatal( + "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); + } + // 不为空返回 + return parser; + } + +``` + + + +### org.springframework.beans.factory.xml.BeanDefinitionParser#parse + +- `org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parse` + +```java + public final BeanDefinition parse(Element element, ParserContext parserContext) { + /** + * {@link AbstractSingleBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)} + */ + AbstractBeanDefinition definition = parseInternal(element, parserContext); + + + } +``` + +### org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#parseInternal + +```java +@Override + protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); + String parentName = getParentName(element); + if (parentName != null) { + builder.getRawBeanDefinition().setParentName(parentName); + } + // 调用自己实现的方法 com.huifer.source.spring.parser.UserBeanDefinitionParser.getBeanClass + Class> beanClass = getBeanClass(element); + if (beanClass != null) { + builder.getRawBeanDefinition().setBeanClass(beanClass); + } + else { + // getBeanClassName 同样也是可以在自定义的解析类中实现 + 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. + // 设置scope + builder.setScope(containingBd.getScope()); + } + if (parserContext.isDefaultLazyInit()) { + // Default-lazy-init applies to custom bean definitions as well. + // 设置 lazy-init + builder.setLazyInit(true); + } + + // 执行解析方法,在自定义解析类中存在com.huifer.source.spring.parser.UserBeanDefinitionParser.doParse + doParse(element, parserContext, builder); + return builder.getBeanDefinition(); + } +``` + + + + + +执行`com.huifer.source.spring.parser.UserBeanDefinitionParser#doParse` + +```JAVA +@Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + // 获取 userName 标签属性值 + String name = element.getAttribute("userName"); + // 获取 emailAddress 标签属性值 + String address = element.getAttribute("emailAddress"); + + if (StringUtils.hasText(name)) { + builder.addPropertyValue("userName", name); + } + if (StringUtils.hasText(address)) { + builder.addPropertyValue("emailAddress", address); + } + } +``` + + + + + diff --git a/images/spring/image-20200109084131415.png b/images/spring/image-20200109084131415.png new file mode 100644 index 0000000..6d99aa1 Binary files /dev/null and b/images/spring/image-20200109084131415.png differ diff --git a/images/spring/image-20200109085606240.png b/images/spring/image-20200109085606240.png new file mode 100644 index 0000000..61883bf Binary files /dev/null and b/images/spring/image-20200109085606240.png differ diff --git a/images/spring/image-20200109090456547.png b/images/spring/image-20200109090456547.png new file mode 100644 index 0000000..19e745c Binary files /dev/null and b/images/spring/image-20200109090456547.png differ diff --git a/images/spring/image-20200109090655157.png b/images/spring/image-20200109090655157.png new file mode 100644 index 0000000..97c431c Binary files /dev/null and b/images/spring/image-20200109090655157.png differ diff --git a/images/spring/image-20200109091216505.png b/images/spring/image-20200109091216505.png new file mode 100644 index 0000000..cbc2d48 Binary files /dev/null and b/images/spring/image-20200109091216505.png differ diff --git a/images/spring/image-20200109092801572.png b/images/spring/image-20200109092801572.png new file mode 100644 index 0000000..043a9ca Binary files /dev/null and b/images/spring/image-20200109092801572.png differ diff --git a/images/spring/image-20200109093242494.png b/images/spring/image-20200109093242494.png new file mode 100644 index 0000000..8d8077f Binary files /dev/null and b/images/spring/image-20200109093242494.png differ diff --git a/images/spring/image-20200109094032421.png b/images/spring/image-20200109094032421.png new file mode 100644 index 0000000..a8dcfb1 Binary files /dev/null and b/images/spring/image-20200109094032421.png differ diff --git a/images/spring/image-20200109094649217.png b/images/spring/image-20200109094649217.png new file mode 100644 index 0000000..2c2b1f2 Binary files /dev/null and b/images/spring/image-20200109094649217.png differ diff --git a/images/spring/image-20200109094654409.png b/images/spring/image-20200109094654409.png new file mode 100644 index 0000000..2c2b1f2 Binary files /dev/null and b/images/spring/image-20200109094654409.png differ diff --git a/images/spring/image-20200109150841916.png b/images/spring/image-20200109150841916.png new file mode 100644 index 0000000..c85d445 Binary files /dev/null and b/images/spring/image-20200109150841916.png differ diff --git a/images/spring/image-20200110093044672.png b/images/spring/image-20200110093044672.png new file mode 100644 index 0000000..514b59c Binary files /dev/null and b/images/spring/image-20200110093044672.png differ diff --git a/images/spring/image-20200115083744268.png b/images/spring/image-20200115083744268.png new file mode 100644 index 0000000..8a465cd Binary files /dev/null and b/images/spring/image-20200115083744268.png differ diff --git a/images/spring/image-20200115084031725.png b/images/spring/image-20200115084031725.png new file mode 100644 index 0000000..6742458 Binary files /dev/null and b/images/spring/image-20200115084031725.png differ diff --git a/images/spring/image-20200115093602651.png b/images/spring/image-20200115093602651.png new file mode 100644 index 0000000..fa04a3c Binary files /dev/null and b/images/spring/image-20200115093602651.png differ diff --git a/images/spring/image-20200115105941265.png b/images/spring/image-20200115105941265.png new file mode 100644 index 0000000..88c456b Binary files /dev/null and b/images/spring/image-20200115105941265.png differ diff --git a/images/spring/image-20200115141708702.png b/images/spring/image-20200115141708702.png new file mode 100644 index 0000000..2c1ada0 Binary files /dev/null and b/images/spring/image-20200115141708702.png differ diff --git a/images/spring/image-20200115143315633.png b/images/spring/image-20200115143315633.png new file mode 100644 index 0000000..6edee36 Binary files /dev/null and b/images/spring/image-20200115143315633.png differ diff --git a/images/spring/image-20200115143456554.png b/images/spring/image-20200115143456554.png new file mode 100644 index 0000000..d19ba94 Binary files /dev/null and b/images/spring/image-20200115143456554.png differ diff --git a/images/spring/image-20200116085344737.png b/images/spring/image-20200116085344737.png new file mode 100644 index 0000000..6f39a30 Binary files /dev/null and b/images/spring/image-20200116085344737.png differ diff --git a/images/spring/image-20200116085423073.png b/images/spring/image-20200116085423073.png new file mode 100644 index 0000000..c40cad2 Binary files /dev/null and b/images/spring/image-20200116085423073.png differ diff --git a/images/spring/image-20200116085726577.png b/images/spring/image-20200116085726577.png new file mode 100644 index 0000000..31a3481 Binary files /dev/null and b/images/spring/image-20200116085726577.png differ diff --git a/images/spring/image-20200116085737632.png b/images/spring/image-20200116085737632.png new file mode 100644 index 0000000..ae8f4cb Binary files /dev/null and b/images/spring/image-20200116085737632.png differ diff --git a/images/spring/image-20200116085927359.png b/images/spring/image-20200116085927359.png new file mode 100644 index 0000000..7a02538 Binary files /dev/null and b/images/spring/image-20200116085927359.png differ diff --git a/images/spring/image-20200116092259944.png b/images/spring/image-20200116092259944.png new file mode 100644 index 0000000..0d20a5a Binary files /dev/null and b/images/spring/image-20200116092259944.png differ diff --git a/images/spring/image-20200116141838601.png b/images/spring/image-20200116141838601.png new file mode 100644 index 0000000..e4ee61b Binary files /dev/null and b/images/spring/image-20200116141838601.png differ diff --git a/images/spring/image-20200116141932486.png b/images/spring/image-20200116141932486.png new file mode 100644 index 0000000..8e06086 Binary files /dev/null and b/images/spring/image-20200116141932486.png differ diff --git a/images/spring/image-20200119085346675.png b/images/spring/image-20200119085346675.png new file mode 100644 index 0000000..2c23ebb Binary files /dev/null and b/images/spring/image-20200119085346675.png differ diff --git a/images/spring/image-20200119085655734.png b/images/spring/image-20200119085655734.png new file mode 100644 index 0000000..18bf79e Binary files /dev/null and b/images/spring/image-20200119085655734.png differ diff --git a/images/spring/image-20200119101017989.png b/images/spring/image-20200119101017989.png new file mode 100644 index 0000000..c8b3ad9 Binary files /dev/null and b/images/spring/image-20200119101017989.png differ diff --git a/images/spring/image-20200119101026726.png b/images/spring/image-20200119101026726.png new file mode 100644 index 0000000..14b6c3e Binary files /dev/null and b/images/spring/image-20200119101026726.png differ diff --git a/images/spring/image-20200119101107820.png b/images/spring/image-20200119101107820.png new file mode 100644 index 0000000..e2546cb Binary files /dev/null and b/images/spring/image-20200119101107820.png differ diff --git a/images/spring/image-20200119101516591.png b/images/spring/image-20200119101516591.png new file mode 100644 index 0000000..4236551 Binary files /dev/null and b/images/spring/image-20200119101516591.png differ
+ * 自定义标签解析 + * + * @param ele the element to parse + * @param containingBd the containing bean definition (if any) + * @return the resulting bean definition + */ + @Nullable + 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)); + } + +``` + + + +- `http://www.huifer.com/schema/user`和我们定义的xsd文件中的url相同,如何找到对应的NamespaceHandler,在`META-INF/spring.handlers`中有定义, + + `http\://www.huifer.com/schema/user=com.huifer.source.spring.parser.UserNamespaceHandler` + + `NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);`这行代码就是获取`spring.handlers`中的定义 + +- 处理方法`org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve` + + + +```java + /** + * Locate the {@link NamespaceHandler} for the supplied namespace URI + * from the configured mappings. + * + * 根据 namespaceUri 获取对应的 {@link NamespaceHandler} + * @param namespaceUri the relevant namespace URI + * @return the located {@link NamespaceHandler}, or {@code null} if none found + */ + @Override + @Nullable + public NamespaceHandler resolve(String namespaceUri) { + // 获取handlerMapping + Map handlerMappings = getHandlerMappings(); + // 从 handlerMapping 中获取类名 + 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); + // 调用init()方法,自定义类中实现 + namespaceHandler.init(); + // 放入缓存 + handlerMappings.put(namespaceUri, namespaceHandler); + // 返回自定义的 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); + } + } + } + +``` + + + +- `org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#getHandlerMappings`跟踪这个方法 + +```JAVA + /** + * Load the specified NamespaceHandler mappings lazily. + * + * 获取handlerMappings + */ + private Map getHandlerMappings() { + Map handlerMappings = this.handlerMappings; + } +``` + + + + + +- 这里直接存在数据了,他是从什么时候加载的? + +- `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions` + + 这个方法在注册bean定义的时候调用 + + ```java + public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { + BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); + int countBefore = getRegistry().getBeanDefinitionCount(); + // 注册方法 + // createReaderContext 初始化HandlerMapping + documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); + return getRegistry().getBeanDefinitionCount() - countBefore; + } + + ``` + +- 继续跟踪`createReaderContext` + + ```java + org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createReaderContext + ``` + + ```java + public XmlReaderContext createReaderContext(Resource resource) { + return new XmlReaderContext(resource, this.problemReporter, this.eventListener, + this.sourceExtractor, this, getNamespaceHandlerResolver()); + } + + ``` + +- 继续跟踪`getNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#getNamespaceHandlerResolver` + + ```java + public NamespaceHandlerResolver getNamespaceHandlerResolver() { + if (this.namespaceHandlerResolver == null) { + this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver(); + } + return this.namespaceHandlerResolver; + } + + ``` + +- 继续跟踪`createDefaultNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createDefaultNamespaceHandlerResolver` + + ```java + protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() { + ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader()); + return new DefaultNamespaceHandlerResolver(cl); + } + ``` + + + +- 继续跟踪`DefaultNamespaceHandlerResolver` + + `org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver` + + ```java + public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) { + this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); + } + + ``` + + 他回到了我们之前疑问的地方 `handlerMappings` 如何出现的 + + 断点 + +  + + ```JAVA + public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) { + this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); + } + ``` + + `public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";` + +  + + 此时还是空 + + 走完 + +  + + ```java + @Override + public String toString() { + return "NamespaceHandlerResolver using mappings " + getHandlerMappings(); + } + + ``` + + + +```JAVA + /** + * Load the specified NamespaceHandler mappings lazily. + * + * 获取handlerMappings + */ + private Map getHandlerMappings() { + Map handlerMappings = this.handlerMappings; + // 缓存不存在 + if (handlerMappings == null) { + synchronized (this) { + handlerMappings = this.handlerMappings; + if (handlerMappings == null) { + if (logger.isTraceEnabled()) { + logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]"); + } + try { + // 将本地文件读出 + Properties mappings = + PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader); + if (logger.isTraceEnabled()) { + logger.trace("Loaded NamespaceHandler mappings: " + mappings); + } + handlerMappings = new ConcurrentHashMap<>(mappings.size()); + // 转换成map结构 + CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings); + this.handlerMappings = handlerMappings; + } + catch (IOException ex) { + throw new IllegalStateException( + "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex); + } + } + } + } + return handlerMappings; + } + +``` + + + + + + + + + +## org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#resolve + +```java + @Override + @Nullable + public NamespaceHandler resolve(String namespaceUri) { + // 获取handlerMapping + Map handlerMappings = getHandlerMappings(); + // 从 handlerMapping 中获取类名 + 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); + // 调用init()方法,自定义类中实现 + namespaceHandler.init(); + // 放入缓存 + handlerMappings.put(namespaceUri, namespaceHandler); + // 返回自定义的 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); + } + } + } + +``` + +执行`init`方法 + +```java +public class UserNamespaceHandler extends NamespaceHandlerSupport { + @Override + public void init() { + registerBeanDefinitionParser("myUser", new UserBeanDefinitionParser()); + } +} +``` + +```java + /** + * Subclasses can call this to register the supplied {@link BeanDefinitionParser} to + * handle the specified element. The element name is the local (non-namespace qualified) + * name. + * + * 将标签名称,标签解析类放入 + */ + protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) { + this.parsers.put(elementName, parser); + } + +``` + + + +- 方法走完,回到开始的方法 + + ```java + /** + * Parse a custom element (outside of the default namespace). + * + * 自定义标签解析 + * + * @param ele the element to parse + * @param containingBd the containing bean definition (if any) + * @return the resulting bean definition + */ + @Nullable + public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { + // 自定义标签解析 + String namespaceUri = getNamespaceURI(ele); + if (namespaceUri == null) { + return null; + } + // 根据命名空间获取处理类 + // org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve + 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)); + } + + ``` + + + + + + + + + +## org.springframework.beans.factory.xml.NamespaceHandler#parse + +- `org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse` + + ```java + @Override + @Nullable + public BeanDefinition parse(Element element, ParserContext parserContext) { + BeanDefinitionParser parser = findParserForElement(element, parserContext); + return (parser != null ? parser.parse(element, parserContext) : null); + } + + ``` + +### org.springframework.beans.factory.xml.NamespaceHandlerSupport#findParserForElement + +```java + @Nullable + private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { + // 获取标签名称 + String localName = parserContext.getDelegate().getLocalName(element); + // 在map中获取对应的标签解析类 + BeanDefinitionParser parser = this.parsers.get(localName); + // 空报错 + if (parser == null) { + parserContext.getReaderContext().fatal( + "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); + } + // 不为空返回 + return parser; + } + +``` + + + +### org.springframework.beans.factory.xml.BeanDefinitionParser#parse + +- `org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parse` + +```java + public final BeanDefinition parse(Element element, ParserContext parserContext) { + /** + * {@link AbstractSingleBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)} + */ + AbstractBeanDefinition definition = parseInternal(element, parserContext); + + + } +``` + +### org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#parseInternal + +```java +@Override + protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); + String parentName = getParentName(element); + if (parentName != null) { + builder.getRawBeanDefinition().setParentName(parentName); + } + // 调用自己实现的方法 com.huifer.source.spring.parser.UserBeanDefinitionParser.getBeanClass + Class> beanClass = getBeanClass(element); + if (beanClass != null) { + builder.getRawBeanDefinition().setBeanClass(beanClass); + } + else { + // getBeanClassName 同样也是可以在自定义的解析类中实现 + 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. + // 设置scope + builder.setScope(containingBd.getScope()); + } + if (parserContext.isDefaultLazyInit()) { + // Default-lazy-init applies to custom bean definitions as well. + // 设置 lazy-init + builder.setLazyInit(true); + } + + // 执行解析方法,在自定义解析类中存在com.huifer.source.spring.parser.UserBeanDefinitionParser.doParse + doParse(element, parserContext, builder); + return builder.getBeanDefinition(); + } +``` + + + + + +执行`com.huifer.source.spring.parser.UserBeanDefinitionParser#doParse` + +```JAVA +@Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + // 获取 userName 标签属性值 + String name = element.getAttribute("userName"); + // 获取 emailAddress 标签属性值 + String address = element.getAttribute("emailAddress"); + + if (StringUtils.hasText(name)) { + builder.addPropertyValue("userName", name); + } + if (StringUtils.hasText(address)) { + builder.addPropertyValue("emailAddress", address); + } + } +``` + + + + + diff --git a/images/spring/image-20200109084131415.png b/images/spring/image-20200109084131415.png new file mode 100644 index 0000000..6d99aa1 Binary files /dev/null and b/images/spring/image-20200109084131415.png differ diff --git a/images/spring/image-20200109085606240.png b/images/spring/image-20200109085606240.png new file mode 100644 index 0000000..61883bf Binary files /dev/null and b/images/spring/image-20200109085606240.png differ diff --git a/images/spring/image-20200109090456547.png b/images/spring/image-20200109090456547.png new file mode 100644 index 0000000..19e745c Binary files /dev/null and b/images/spring/image-20200109090456547.png differ diff --git a/images/spring/image-20200109090655157.png b/images/spring/image-20200109090655157.png new file mode 100644 index 0000000..97c431c Binary files /dev/null and b/images/spring/image-20200109090655157.png differ diff --git a/images/spring/image-20200109091216505.png b/images/spring/image-20200109091216505.png new file mode 100644 index 0000000..cbc2d48 Binary files /dev/null and b/images/spring/image-20200109091216505.png differ diff --git a/images/spring/image-20200109092801572.png b/images/spring/image-20200109092801572.png new file mode 100644 index 0000000..043a9ca Binary files /dev/null and b/images/spring/image-20200109092801572.png differ diff --git a/images/spring/image-20200109093242494.png b/images/spring/image-20200109093242494.png new file mode 100644 index 0000000..8d8077f Binary files /dev/null and b/images/spring/image-20200109093242494.png differ diff --git a/images/spring/image-20200109094032421.png b/images/spring/image-20200109094032421.png new file mode 100644 index 0000000..a8dcfb1 Binary files /dev/null and b/images/spring/image-20200109094032421.png differ diff --git a/images/spring/image-20200109094649217.png b/images/spring/image-20200109094649217.png new file mode 100644 index 0000000..2c2b1f2 Binary files /dev/null and b/images/spring/image-20200109094649217.png differ diff --git a/images/spring/image-20200109094654409.png b/images/spring/image-20200109094654409.png new file mode 100644 index 0000000..2c2b1f2 Binary files /dev/null and b/images/spring/image-20200109094654409.png differ diff --git a/images/spring/image-20200109150841916.png b/images/spring/image-20200109150841916.png new file mode 100644 index 0000000..c85d445 Binary files /dev/null and b/images/spring/image-20200109150841916.png differ diff --git a/images/spring/image-20200110093044672.png b/images/spring/image-20200110093044672.png new file mode 100644 index 0000000..514b59c Binary files /dev/null and b/images/spring/image-20200110093044672.png differ diff --git a/images/spring/image-20200115083744268.png b/images/spring/image-20200115083744268.png new file mode 100644 index 0000000..8a465cd Binary files /dev/null and b/images/spring/image-20200115083744268.png differ diff --git a/images/spring/image-20200115084031725.png b/images/spring/image-20200115084031725.png new file mode 100644 index 0000000..6742458 Binary files /dev/null and b/images/spring/image-20200115084031725.png differ diff --git a/images/spring/image-20200115093602651.png b/images/spring/image-20200115093602651.png new file mode 100644 index 0000000..fa04a3c Binary files /dev/null and b/images/spring/image-20200115093602651.png differ diff --git a/images/spring/image-20200115105941265.png b/images/spring/image-20200115105941265.png new file mode 100644 index 0000000..88c456b Binary files /dev/null and b/images/spring/image-20200115105941265.png differ diff --git a/images/spring/image-20200115141708702.png b/images/spring/image-20200115141708702.png new file mode 100644 index 0000000..2c1ada0 Binary files /dev/null and b/images/spring/image-20200115141708702.png differ diff --git a/images/spring/image-20200115143315633.png b/images/spring/image-20200115143315633.png new file mode 100644 index 0000000..6edee36 Binary files /dev/null and b/images/spring/image-20200115143315633.png differ diff --git a/images/spring/image-20200115143456554.png b/images/spring/image-20200115143456554.png new file mode 100644 index 0000000..d19ba94 Binary files /dev/null and b/images/spring/image-20200115143456554.png differ diff --git a/images/spring/image-20200116085344737.png b/images/spring/image-20200116085344737.png new file mode 100644 index 0000000..6f39a30 Binary files /dev/null and b/images/spring/image-20200116085344737.png differ diff --git a/images/spring/image-20200116085423073.png b/images/spring/image-20200116085423073.png new file mode 100644 index 0000000..c40cad2 Binary files /dev/null and b/images/spring/image-20200116085423073.png differ diff --git a/images/spring/image-20200116085726577.png b/images/spring/image-20200116085726577.png new file mode 100644 index 0000000..31a3481 Binary files /dev/null and b/images/spring/image-20200116085726577.png differ diff --git a/images/spring/image-20200116085737632.png b/images/spring/image-20200116085737632.png new file mode 100644 index 0000000..ae8f4cb Binary files /dev/null and b/images/spring/image-20200116085737632.png differ diff --git a/images/spring/image-20200116085927359.png b/images/spring/image-20200116085927359.png new file mode 100644 index 0000000..7a02538 Binary files /dev/null and b/images/spring/image-20200116085927359.png differ diff --git a/images/spring/image-20200116092259944.png b/images/spring/image-20200116092259944.png new file mode 100644 index 0000000..0d20a5a Binary files /dev/null and b/images/spring/image-20200116092259944.png differ diff --git a/images/spring/image-20200116141838601.png b/images/spring/image-20200116141838601.png new file mode 100644 index 0000000..e4ee61b Binary files /dev/null and b/images/spring/image-20200116141838601.png differ diff --git a/images/spring/image-20200116141932486.png b/images/spring/image-20200116141932486.png new file mode 100644 index 0000000..8e06086 Binary files /dev/null and b/images/spring/image-20200116141932486.png differ diff --git a/images/spring/image-20200119085346675.png b/images/spring/image-20200119085346675.png new file mode 100644 index 0000000..2c23ebb Binary files /dev/null and b/images/spring/image-20200119085346675.png differ diff --git a/images/spring/image-20200119085655734.png b/images/spring/image-20200119085655734.png new file mode 100644 index 0000000..18bf79e Binary files /dev/null and b/images/spring/image-20200119085655734.png differ diff --git a/images/spring/image-20200119101017989.png b/images/spring/image-20200119101017989.png new file mode 100644 index 0000000..c8b3ad9 Binary files /dev/null and b/images/spring/image-20200119101017989.png differ diff --git a/images/spring/image-20200119101026726.png b/images/spring/image-20200119101026726.png new file mode 100644 index 0000000..14b6c3e Binary files /dev/null and b/images/spring/image-20200119101026726.png differ diff --git a/images/spring/image-20200119101107820.png b/images/spring/image-20200119101107820.png new file mode 100644 index 0000000..e2546cb Binary files /dev/null and b/images/spring/image-20200119101107820.png differ diff --git a/images/spring/image-20200119101516591.png b/images/spring/image-20200119101516591.png new file mode 100644 index 0000000..4236551 Binary files /dev/null and b/images/spring/image-20200119101516591.png differ
+ * 自定义标签解析 + * + * @param ele the element to parse + * @param containingBd the containing bean definition (if any) + * @return the resulting bean definition + */ + @Nullable + public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { + // 自定义标签解析 + String namespaceUri = getNamespaceURI(ele); + if (namespaceUri == null) { + return null; + } + // 根据命名空间获取处理类 + // org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve + 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)); + } + + ``` + + + + + + + + + +## org.springframework.beans.factory.xml.NamespaceHandler#parse + +- `org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse` + + ```java + @Override + @Nullable + public BeanDefinition parse(Element element, ParserContext parserContext) { + BeanDefinitionParser parser = findParserForElement(element, parserContext); + return (parser != null ? parser.parse(element, parserContext) : null); + } + + ``` + +### org.springframework.beans.factory.xml.NamespaceHandlerSupport#findParserForElement + +```java + @Nullable + private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { + // 获取标签名称 + String localName = parserContext.getDelegate().getLocalName(element); + // 在map中获取对应的标签解析类 + BeanDefinitionParser parser = this.parsers.get(localName); + // 空报错 + if (parser == null) { + parserContext.getReaderContext().fatal( + "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); + } + // 不为空返回 + return parser; + } + +``` + + + +### org.springframework.beans.factory.xml.BeanDefinitionParser#parse + +- `org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parse` + +```java + public final BeanDefinition parse(Element element, ParserContext parserContext) { + /** + * {@link AbstractSingleBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)} + */ + AbstractBeanDefinition definition = parseInternal(element, parserContext); + + + } +``` + +### org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#parseInternal + +```java +@Override + protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); + String parentName = getParentName(element); + if (parentName != null) { + builder.getRawBeanDefinition().setParentName(parentName); + } + // 调用自己实现的方法 com.huifer.source.spring.parser.UserBeanDefinitionParser.getBeanClass + Class> beanClass = getBeanClass(element); + if (beanClass != null) { + builder.getRawBeanDefinition().setBeanClass(beanClass); + } + else { + // getBeanClassName 同样也是可以在自定义的解析类中实现 + 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. + // 设置scope + builder.setScope(containingBd.getScope()); + } + if (parserContext.isDefaultLazyInit()) { + // Default-lazy-init applies to custom bean definitions as well. + // 设置 lazy-init + builder.setLazyInit(true); + } + + // 执行解析方法,在自定义解析类中存在com.huifer.source.spring.parser.UserBeanDefinitionParser.doParse + doParse(element, parserContext, builder); + return builder.getBeanDefinition(); + } +``` + + + + + +执行`com.huifer.source.spring.parser.UserBeanDefinitionParser#doParse` + +```JAVA +@Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + // 获取 userName 标签属性值 + String name = element.getAttribute("userName"); + // 获取 emailAddress 标签属性值 + String address = element.getAttribute("emailAddress"); + + if (StringUtils.hasText(name)) { + builder.addPropertyValue("userName", name); + } + if (StringUtils.hasText(address)) { + builder.addPropertyValue("emailAddress", address); + } + } +``` + + + + + diff --git a/images/spring/image-20200109084131415.png b/images/spring/image-20200109084131415.png new file mode 100644 index 0000000..6d99aa1 Binary files /dev/null and b/images/spring/image-20200109084131415.png differ diff --git a/images/spring/image-20200109085606240.png b/images/spring/image-20200109085606240.png new file mode 100644 index 0000000..61883bf Binary files /dev/null and b/images/spring/image-20200109085606240.png differ diff --git a/images/spring/image-20200109090456547.png b/images/spring/image-20200109090456547.png new file mode 100644 index 0000000..19e745c Binary files /dev/null and b/images/spring/image-20200109090456547.png differ diff --git a/images/spring/image-20200109090655157.png b/images/spring/image-20200109090655157.png new file mode 100644 index 0000000..97c431c Binary files /dev/null and b/images/spring/image-20200109090655157.png differ diff --git a/images/spring/image-20200109091216505.png b/images/spring/image-20200109091216505.png new file mode 100644 index 0000000..cbc2d48 Binary files /dev/null and b/images/spring/image-20200109091216505.png differ diff --git a/images/spring/image-20200109092801572.png b/images/spring/image-20200109092801572.png new file mode 100644 index 0000000..043a9ca Binary files /dev/null and b/images/spring/image-20200109092801572.png differ diff --git a/images/spring/image-20200109093242494.png b/images/spring/image-20200109093242494.png new file mode 100644 index 0000000..8d8077f Binary files /dev/null and b/images/spring/image-20200109093242494.png differ diff --git a/images/spring/image-20200109094032421.png b/images/spring/image-20200109094032421.png new file mode 100644 index 0000000..a8dcfb1 Binary files /dev/null and b/images/spring/image-20200109094032421.png differ diff --git a/images/spring/image-20200109094649217.png b/images/spring/image-20200109094649217.png new file mode 100644 index 0000000..2c2b1f2 Binary files /dev/null and b/images/spring/image-20200109094649217.png differ diff --git a/images/spring/image-20200109094654409.png b/images/spring/image-20200109094654409.png new file mode 100644 index 0000000..2c2b1f2 Binary files /dev/null and b/images/spring/image-20200109094654409.png differ diff --git a/images/spring/image-20200109150841916.png b/images/spring/image-20200109150841916.png new file mode 100644 index 0000000..c85d445 Binary files /dev/null and b/images/spring/image-20200109150841916.png differ diff --git a/images/spring/image-20200110093044672.png b/images/spring/image-20200110093044672.png new file mode 100644 index 0000000..514b59c Binary files /dev/null and b/images/spring/image-20200110093044672.png differ diff --git a/images/spring/image-20200115083744268.png b/images/spring/image-20200115083744268.png new file mode 100644 index 0000000..8a465cd Binary files /dev/null and b/images/spring/image-20200115083744268.png differ diff --git a/images/spring/image-20200115084031725.png b/images/spring/image-20200115084031725.png new file mode 100644 index 0000000..6742458 Binary files /dev/null and b/images/spring/image-20200115084031725.png differ diff --git a/images/spring/image-20200115093602651.png b/images/spring/image-20200115093602651.png new file mode 100644 index 0000000..fa04a3c Binary files /dev/null and b/images/spring/image-20200115093602651.png differ diff --git a/images/spring/image-20200115105941265.png b/images/spring/image-20200115105941265.png new file mode 100644 index 0000000..88c456b Binary files /dev/null and b/images/spring/image-20200115105941265.png differ diff --git a/images/spring/image-20200115141708702.png b/images/spring/image-20200115141708702.png new file mode 100644 index 0000000..2c1ada0 Binary files /dev/null and b/images/spring/image-20200115141708702.png differ diff --git a/images/spring/image-20200115143315633.png b/images/spring/image-20200115143315633.png new file mode 100644 index 0000000..6edee36 Binary files /dev/null and b/images/spring/image-20200115143315633.png differ diff --git a/images/spring/image-20200115143456554.png b/images/spring/image-20200115143456554.png new file mode 100644 index 0000000..d19ba94 Binary files /dev/null and b/images/spring/image-20200115143456554.png differ diff --git a/images/spring/image-20200116085344737.png b/images/spring/image-20200116085344737.png new file mode 100644 index 0000000..6f39a30 Binary files /dev/null and b/images/spring/image-20200116085344737.png differ diff --git a/images/spring/image-20200116085423073.png b/images/spring/image-20200116085423073.png new file mode 100644 index 0000000..c40cad2 Binary files /dev/null and b/images/spring/image-20200116085423073.png differ diff --git a/images/spring/image-20200116085726577.png b/images/spring/image-20200116085726577.png new file mode 100644 index 0000000..31a3481 Binary files /dev/null and b/images/spring/image-20200116085726577.png differ diff --git a/images/spring/image-20200116085737632.png b/images/spring/image-20200116085737632.png new file mode 100644 index 0000000..ae8f4cb Binary files /dev/null and b/images/spring/image-20200116085737632.png differ diff --git a/images/spring/image-20200116085927359.png b/images/spring/image-20200116085927359.png new file mode 100644 index 0000000..7a02538 Binary files /dev/null and b/images/spring/image-20200116085927359.png differ diff --git a/images/spring/image-20200116092259944.png b/images/spring/image-20200116092259944.png new file mode 100644 index 0000000..0d20a5a Binary files /dev/null and b/images/spring/image-20200116092259944.png differ diff --git a/images/spring/image-20200116141838601.png b/images/spring/image-20200116141838601.png new file mode 100644 index 0000000..e4ee61b Binary files /dev/null and b/images/spring/image-20200116141838601.png differ diff --git a/images/spring/image-20200116141932486.png b/images/spring/image-20200116141932486.png new file mode 100644 index 0000000..8e06086 Binary files /dev/null and b/images/spring/image-20200116141932486.png differ diff --git a/images/spring/image-20200119085346675.png b/images/spring/image-20200119085346675.png new file mode 100644 index 0000000..2c23ebb Binary files /dev/null and b/images/spring/image-20200119085346675.png differ diff --git a/images/spring/image-20200119085655734.png b/images/spring/image-20200119085655734.png new file mode 100644 index 0000000..18bf79e Binary files /dev/null and b/images/spring/image-20200119085655734.png differ diff --git a/images/spring/image-20200119101017989.png b/images/spring/image-20200119101017989.png new file mode 100644 index 0000000..c8b3ad9 Binary files /dev/null and b/images/spring/image-20200119101017989.png differ diff --git a/images/spring/image-20200119101026726.png b/images/spring/image-20200119101026726.png new file mode 100644 index 0000000..14b6c3e Binary files /dev/null and b/images/spring/image-20200119101026726.png differ diff --git a/images/spring/image-20200119101107820.png b/images/spring/image-20200119101107820.png new file mode 100644 index 0000000..e2546cb Binary files /dev/null and b/images/spring/image-20200119101107820.png differ diff --git a/images/spring/image-20200119101516591.png b/images/spring/image-20200119101516591.png new file mode 100644 index 0000000..4236551 Binary files /dev/null and b/images/spring/image-20200119101516591.png differ