diff --git "a/week_07/54/Spring AOP\350\277\220\350\241\214\346\227\266\345\272\217\345\233\276.md" "b/week_07/54/Spring AOP\350\277\220\350\241\214\346\227\266\345\272\217\345\233\276.md" new file mode 100644 index 0000000000000000000000000000000000000000..12cbe2a3b56df3c617640ec7d7e49ac6c6301394 --- /dev/null +++ "b/week_07/54/Spring AOP\350\277\220\350\241\214\346\227\266\345\272\217\345\233\276.md" @@ -0,0 +1,97 @@ +# Spring AOP运行时序图分析 + + +### 运行时序图 +见spring aop jdk运行时序图 +### 原理分析 + +##### jdk动态代理 + +DefaultAopProxyFactory类里面可以发现直接实例化JdkDynamicAopProxy类 +```java +public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { + if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) { + return new JdkDynamicAopProxy(config); + } else { + Class targetClass = config.getTargetClass(); + if (targetClass == null) { + throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation."); + } else { + return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config)); + } + } + } +``` +JdkDynamicAopProxy类核心方法invoke实现 +```java + @Nullable + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + Object oldProxy = null; + boolean setProxyContext = false; + TargetSource targetSource = this.advised.targetSource; + Object target = null; + + Object retVal; + try { + if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { + Boolean var19 = this.equals(args[0]); + return var19; + } + + if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { + Integer var18 = this.hashCode(); + return var18; + } + + if (method.getDeclaringClass() == DecoratingProxy.class) { + Class var17 = AopProxyUtils.ultimateTargetClass(this.advised); + return var17; + } + + if (this.advised.opaque || !method.getDeclaringClass().isInterface() || !method.getDeclaringClass().isAssignableFrom(Advised.class)) { + if (this.advised.exposeProxy) { + oldProxy = AopContext.setCurrentProxy(proxy); + setProxyContext = true; + } + + // 获取target + target = targetSource.getTarget(); + Class targetClass = target != null ? target.getClass() : null; + // 获取所有拦截器以链的形式返回 + List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); + if (chain.isEmpty()) { + Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); + retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); + } else { + // 准备好参数 + MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); + // 执行 + retVal = invocation.proceed(); + } + + Class returnType = method.getReturnType(); + if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { + retVal = proxy; + } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { + throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method); + } + + Object var13 = retVal; + return var13; + } + + retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); + } finally { + if (target != null && !targetSource.isStatic()) { + targetSource.releaseTarget(target); + } + + if (setProxyContext) { + AopContext.setCurrentProxy(oldProxy); + } + + } + + return retVal; + } +``` \ No newline at end of file diff --git "a/week_07/54/Spring DI\350\277\220\350\241\214\346\227\266\345\272\217\345\233\276.md" "b/week_07/54/Spring DI\350\277\220\350\241\214\346\227\266\345\272\217\345\233\276.md" new file mode 100644 index 0000000000000000000000000000000000000000..7a803d69436f6127f7e78f63cd5b91b10b69a968 --- /dev/null +++ "b/week_07/54/Spring DI\350\277\220\350\241\214\346\227\266\345\272\217\345\233\276.md" @@ -0,0 +1,286 @@ +# Spring DI运行时序图分析 + +### 运行时序图 +见spring di运行时序图 +### 原理分析 + +AbstractBeanFactory实现BeanFactory接口,通过getBean加载bean,靠doGetBean实现 + +```java +protected T doGetBean(String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { + String beanName = this.transformedBeanName(name); + // 从缓存中获取 + Object sharedInstance = this.getSingleton(beanName); + Object bean; + if (sharedInstance != null && args == null) { + if (this.logger.isTraceEnabled()) { + if (this.isSingletonCurrentlyInCreation(beanName)) { + this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); + } else { + this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); + } + } + + bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null); + } else { + // 缓存中没有则创建 + if (this.isPrototypeCurrentlyInCreation(beanName)) { + throw new BeanCurrentlyInCreationException(beanName); + } + + BeanFactory parentBeanFactory = this.getParentBeanFactory(); + if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) { + String nameToLookup = this.originalBeanName(name); + if (parentBeanFactory instanceof AbstractBeanFactory) { + return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly); + } + + if (args != null) { + return parentBeanFactory.getBean(nameToLookup, args); + } + + if (requiredType != null) { + return parentBeanFactory.getBean(nameToLookup, requiredType); + } + + return parentBeanFactory.getBean(nameToLookup); + } + + if (!typeCheckOnly) { + // 标记 + this.markBeanAsCreated(beanName); + } + + try { + // 获取该 bean 的 beanDefintion + RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName); + this.checkMergedBeanDefinition(mbd, beanName, args); + String[] dependsOn = mbd.getDependsOn(); + String[] var11; + if (dependsOn != null) { + var11 = dependsOn; + int var12 = dependsOn.length; + + for(int var13 = 0; var13 < var12; ++var13) { + String dep = var11[var13]; + if (this.isDependent(beanName, dep)) { + throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); + } + + this.registerDependentBean(dep, beanName); + + try { + this.getBean(dep); + } catch (NoSuchBeanDefinitionException var24) { + throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24); + } + } + } + + if (mbd.isSingleton()) { + sharedInstance = this.getSingleton(beanName, () -> { + try { + return this.createBean(beanName, mbd, args); + } catch (BeansException var5) { + this.destroySingleton(beanName); + throw var5; + } + }); + bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd); + } else if (mbd.isPrototype()) { + var11 = null; + + Object prototypeInstance; + try { + this.beforePrototypeCreation(beanName); + prototypeInstance = this.createBean(beanName, mbd, args); + } finally { + this.afterPrototypeCreation(beanName); + } + + bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); + } else { + String scopeName = mbd.getScope(); + Scope scope = (Scope)this.scopes.get(scopeName); + if (scope == null) { + throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); + } + + try { + Object scopedInstance = scope.get(beanName, () -> { + this.beforePrototypeCreation(beanName); + + Object var4; + try { + var4 = this.createBean(beanName, mbd, args); + } finally { + this.afterPrototypeCreation(beanName); + } + + return var4; + }); + bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd); + } catch (IllegalStateException var23) { + throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", var23); + } + } + } catch (BeansException var26) { + this.cleanupAfterBeanCreationFailure(beanName); + throw var26; + } + } + + if (requiredType != null && !requiredType.isInstance(bean)) { + try { + T convertedBean = this.getTypeConverter().convertIfNecessary(bean, requiredType); + if (convertedBean == null) { + throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); + } else { + return convertedBean; + } + } catch (TypeMismatchException var25) { + if (this.logger.isTraceEnabled()) { + this.logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var25); + } + + throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); + } + } else { + return bean; + } + } +``` +doGetBean里面的查看是否存在缓存中,不存在则AbstractAutowireCapableBeanFactory类的createBean方法创建 + +```java +protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { + if (this.logger.isTraceEnabled()) { + this.logger.trace("Creating instance of bean '" + beanName + "'"); + } + + RootBeanDefinition mbdToUse = mbd; + Class resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]); + if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { + mbdToUse = new RootBeanDefinition(mbd); + mbdToUse.setBeanClass(resolvedClass); + } + + try { + mbdToUse.prepareMethodOverrides(); + } catch (BeanDefinitionValidationException var9) { + throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var9); + } + + Object beanInstance; + try { + beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse); + if (beanInstance != null) { + return beanInstance; + } + } catch (Throwable var10) { + throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10); + } + + try { + beanInstance = this.doCreateBean(beanName, mbdToUse, args); + if (this.logger.isTraceEnabled()) { + this.logger.trace("Finished creating instance of bean '" + beanName + "'"); + } + + return beanInstance; + } catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) { + throw var7; + } catch (Throwable var8) { + throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8); + } + } +``` +调用doCreateBean方法对bean的依赖注入 + ```java +protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { + BeanWrapper instanceWrapper = null; + if (mbd.isSingleton()) { + instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName); + } + + if (instanceWrapper == null) { + instanceWrapper = this.createBeanInstance(beanName, mbd, args); + } + + Object bean = instanceWrapper.getWrappedInstance(); + Class beanType = instanceWrapper.getWrappedClass(); + if (beanType != NullBean.class) { + mbd.resolvedTargetType = beanType; + } + + synchronized(mbd.postProcessingLock) { + if (!mbd.postProcessed) { + try { + this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); + } catch (Throwable var17) { + throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17); + } + + mbd.postProcessed = true; + } + } + + boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName); + if (earlySingletonExposure) { + if (this.logger.isTraceEnabled()) { + this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); + } + + this.addSingletonFactory(beanName, () -> { + return this.getEarlyBeanReference(beanName, mbd, bean); + }); + } + + Object exposedObject = bean; + + try { + this.populateBean(beanName, mbd, instanceWrapper); + exposedObject = this.initializeBean(beanName, exposedObject, mbd); + } catch (Throwable var18) { + if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) { + throw (BeanCreationException)var18; + } + + throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18); + } + + if (earlySingletonExposure) { + Object earlySingletonReference = this.getSingleton(beanName, false); + if (earlySingletonReference != null) { + if (exposedObject == bean) { + exposedObject = earlySingletonReference; + } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) { + String[] dependentBeans = this.getDependentBeans(beanName); + Set actualDependentBeans = new LinkedHashSet(dependentBeans.length); + String[] var12 = dependentBeans; + int var13 = dependentBeans.length; + + for(int var14 = 0; var14 < var13; ++var14) { + String dependentBean = var12[var14]; + if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { + actualDependentBeans.add(dependentBean); + } + } + + if (!actualDependentBeans.isEmpty()) { + throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); + } + } + } + } + + try { + // 实现依赖注入 + this.registerDisposableBeanIfNecessary(beanName, bean, mbd); + return exposedObject; + } catch (BeanDefinitionValidationException var16) { + throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16); + } + } +``` + diff --git "a/week_07/54/Spring IOC\350\277\220\350\241\214\346\227\266\345\272\217\345\233\276.md" "b/week_07/54/Spring IOC\350\277\220\350\241\214\346\227\266\345\272\217\345\233\276.md" new file mode 100644 index 0000000000000000000000000000000000000000..109575846ee80e39cedc9ace9a91ed3b0f781726 --- /dev/null +++ "b/week_07/54/Spring IOC\350\277\220\350\241\214\346\227\266\345\272\217\345\233\276.md" @@ -0,0 +1,66 @@ +# Spring IOC运行时序图分析 + +### 一.Spring IOC运行时序图 +见spring ioc运行时序图 +### 二.分析IOC +在main对xml进行加载,调用ClassPathXmlApplicationContext类 +```java +public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { + super(parent); + this.setConfigLocations(configLocations); + if (refresh) { + this.refresh(); + } + + } +``` +AbstractRefreshableConfigApplicationContext类的setConfigLocations方法可以发现**配置文件通过字符串数组的形式进行传递** +AbstractApplicationContext类的refresh()方法 + ```java +public void refresh() throws BeansException, IllegalStateException { + synchronized(this.startupShutdownMonitor) { + // 这个方法设置context的启动日期;设置context当前的状态,是活动状态还是关闭状态; + // 初始化context environment(上下文环境)中的占位符属性来源;验证所有必需的属性. + this.prepareRefresh(); + // 让这个类(AbstractApplicationContext)的子类刷新内部bean工厂。实际上就是重新创建一个bean工厂 + ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); + // 工厂设置配置 + this.prepareBeanFactory(beanFactory); + + try { + // 对工厂配置的进一步处理 + this.postProcessBeanFactory(beanFactory); + // 调用所有的bean工厂处理器(BeanFactoryPostProcessor)对bean工厂进行一些处理 + this.invokeBeanFactoryPostProcessors(beanFactory); + // 注册用来拦截bean创建的BeanPostProcessor + this.registerBeanPostProcessors(beanFactory); + // 初始化消息资源 + this.initMessageSource(); + // 初始化事件广播器 + this.initApplicationEventMulticaster(); + // 初始化特殊bean + this.onRefresh(); + // 注册监视器 + this.registerListeners(); + // 完成bean工厂初始化 + this.finishBeanFactoryInitialization(beanFactory); + // 完成context的刷新 + this.finishRefresh(); + } catch (BeansException var9) { + // 如果出错则销毁bean和取消刷新 + if (this.logger.isWarnEnabled()) { + this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9); + } + this.destroyBeans(); + this.cancelRefresh(var9); + throw var9; + } finally { + this.resetCommonCaches(); + } + + } + } +``` + + + diff --git "a/week_07/54/Spring MVC\350\277\220\350\241\214\346\227\266\345\272\217\345\233\276.md" "b/week_07/54/Spring MVC\350\277\220\350\241\214\346\227\266\345\272\217\345\233\276.md" new file mode 100644 index 0000000000000000000000000000000000000000..9480e7ece6642a9a98fbfda966db5b4b3f3b6e4d --- /dev/null +++ "b/week_07/54/Spring MVC\350\277\220\350\241\214\346\227\266\345\272\217\345\233\276.md" @@ -0,0 +1,102 @@ +# Spring MVC运行时序图分析 + + +### 运行时序图 +见spring mvc运行时序图 +### 原理分析 + +主要围绕着DispatcherServlet类来执行的 +![](https://img-blog.csdn.net/20180522162744760?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbndlaWhwdQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) + +DispatcherServlet类中的属性beans: + +HandlerMapping:用于handlers映射请求和一系列的对于拦截器的前处理和后处理,大部分用@Controller注解。 + +HandlerAdapter:帮助DispatcherServlet处理映射请求处理程序的适配器,而不用考虑实际调用的是 哪个处理程序。 + +HandlerExceptionResolver:处理映射异常。 + +ViewResolver:根据实际配置解析实际的View类型。 + +LocaleResolver:解决客户正在使用的区域设置以及可能的时区,以便能够提供国际化视野。 + +ThemeResolver:解决Web应用程序可以使用的主题,例如提供个性化布局。 + +MultipartResolver:解析多部分请求,以支持从HTML表单上传文件。 + +FlashMapManager:存储并检索可用于将一个请求属性传递到另一个请求的input和output的FlashMap,通常用于重定向。 + +在Web MVC框架中,每个DispatcherServlet都拥自己的WebApplicationContext,它继承了ApplicationContext。WebApplicationContext包含了其上下文和Servlet实例之间共享的所有的基础框架beans。 + +通过doService方法设置了request的相关属性,然后调用doDispatch方法 +```java +protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { + HttpServletRequest processedRequest = request; + HandlerExecutionChain mappedHandler = null; + boolean multipartRequestParsed = false; + WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); + + try { + try { + ModelAndView mv = null; + Object dispatchException = null; + + try { + processedRequest = this.checkMultipart(request); + multipartRequestParsed = processedRequest != request; + mappedHandler = this.getHandler(processedRequest); + if (mappedHandler == null) { + this.noHandlerFound(processedRequest, response); + return; + } + + HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler()); + String method = request.getMethod(); + boolean isGet = "GET".equals(method); + if (isGet || "HEAD".equals(method)) { + long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); + if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) { + return; + } + } + + if (!mappedHandler.applyPreHandle(processedRequest, response)) { + return; + } + + mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); + if (asyncManager.isConcurrentHandlingStarted()) { + return; + } + + this.applyDefaultViewName(processedRequest, mv); + mappedHandler.applyPostHandle(processedRequest, response, mv); + } catch (Exception var20) { + dispatchException = var20; + } catch (Throwable var21) { + dispatchException = new NestedServletException("Handler dispatch failed", var21); + } + + this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException); + } catch (Exception var22) { + this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22); + } catch (Throwable var23) { + this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23)); + } + + } finally { + if (asyncManager.isConcurrentHandlingStarted()) { + if (mappedHandler != null) { + mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); + } + } else if (multipartRequestParsed) { + this.cleanupMultipart(processedRequest); + } + + } + } +``` +通过handlerMapping获得Handler,然后生成对应的HandlerAdapter来处理数据逻辑(controller层),获得了一个ModelAndView对象。HandlerAdpater 处理的结果是创建了一个ModelAndView对象,但不代表这个ModelAndView对象中包含了完整的信息。 随后DispatcherServlet使用RequestToViewNameResolver给ModelAndView设置viewName。最后调用processDispatchResult来处理界面逻辑(异常和view层)。 +### 总结 + +几个组件之间的执行流程是 handlerMapping ———> handlerAdapter———>requestToViewNameResolver ———>handlerExceptionResolver———>viewResolver———>View \ No newline at end of file diff --git a/week_07/54/di.png b/week_07/54/di.png new file mode 100644 index 0000000000000000000000000000000000000000..33a43a10865c97471ffcffe6b4d0aadb6ed4f065 Binary files /dev/null and b/week_07/54/di.png differ diff --git a/week_07/54/spring aop jdk.png b/week_07/54/spring aop jdk.png new file mode 100644 index 0000000000000000000000000000000000000000..afdd37710176ff3d4bd5aa954ad577a3744f2374 Binary files /dev/null and b/week_07/54/spring aop jdk.png differ diff --git a/week_07/54/spring aop2.png b/week_07/54/spring aop2.png new file mode 100644 index 0000000000000000000000000000000000000000..fb6a506319ab155a1b31fbc261d0ee25f3fdd6f7 Binary files /dev/null and b/week_07/54/spring aop2.png differ diff --git a/week_07/54/spring di.png b/week_07/54/spring di.png new file mode 100644 index 0000000000000000000000000000000000000000..1139b86d1587c59b65569274d3bdb8c6bba25e2b Binary files /dev/null and b/week_07/54/spring di.png differ diff --git a/week_07/54/spring ioc 1.png b/week_07/54/spring ioc 1.png new file mode 100644 index 0000000000000000000000000000000000000000..85f06f8cbf1d0710c42d032598b4d1ec3351caa0 Binary files /dev/null and b/week_07/54/spring ioc 1.png differ diff --git a/week_07/54/spring ioc 2.png b/week_07/54/spring ioc 2.png new file mode 100644 index 0000000000000000000000000000000000000000..ef8cbadc60fa5a75b4ad8b843d333d1d9815542b Binary files /dev/null and b/week_07/54/spring ioc 2.png differ diff --git a/week_07/54/spring mvc.png b/week_07/54/spring mvc.png new file mode 100644 index 0000000000000000000000000000000000000000..0face7abd4d7f22365d8a13fe5c7ebbf4a956973 Binary files /dev/null and b/week_07/54/spring mvc.png differ