diff --git a/second/week_07/87/aop.assets/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5NjA5Mzg4,size_16,color_FFFFFF,t_70.png b/second/week_07/87/aop.assets/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5NjA5Mzg4,size_16,color_FFFFFF,t_70.png new file mode 100644 index 0000000000000000000000000000000000000000..0e867cc6311b5de7b67f545f34871a5a6a4e2a05 Binary files /dev/null and b/second/week_07/87/aop.assets/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5NjA5Mzg4,size_16,color_FFFFFF,t_70.png differ diff --git a/second/week_07/87/aop.md b/second/week_07/87/aop.md new file mode 100644 index 0000000000000000000000000000000000000000..5c8d1e967c651c9543d00d59ed4e7963b6215d70 --- /dev/null +++ b/second/week_07/87/aop.md @@ -0,0 +1,78 @@ +# AOP 时序 + +![img](aop.assets/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5NjA5Mzg4,size_16,color_FFFFFF,t_70.png) + +## 场景 + +AOP 是OOP 的延续,是Aspect Oriented Programming 的缩写,意思是面向切面编程。可以通过预 +编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。AOP +设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP 可以说也是这种目标的一种实现。 +我们现在做的一些非业务,如:日志、事务、安全等都会写在业务代码中(也即是说,这些非业务类横切 +于业务类),但这些代码往往是重复,复制——粘贴式的代码会给程序的维护带来不便,AOP 就实现了 +把这些业务需求与系统需求分开来做。这种解决的方式也称代理机制。 + +## 几个概念 + +### 1、切面(Aspect) + +官方的抽象定义为“ 一个关注点的模块化,这个关注点可能会横切多个对象” 。“ 切面”在 +ApplicationContext 中aop:aspect来配置。 +连接点(Joinpoint) :程序执行过程中的某一行为,例如,MemberService .get 的调用或者 +MemberService .delete 抛出异常等行为。 + +### 2、通知(Advice) + +“切面”对于某个“连接点”所产生的动作。其中,一个“切面”可以包含多个“Advice”。 + +### 3、切入点(Pointcut) + +匹配连接点的断言,在AOP 中通知和一个切入点表达式关联。切面中的所有通知所关注的连接点,都 +由切入点表达式来决定。 + +### 4、目标对象(Target Object) + +被一个或者多个切面所通知的对象。例如,AServcieImpl 和BServiceImpl,当然在实际运行时,Spring +AOP 采用代理实现,实际AOP 操作的是TargetObject 的代理对象。 + +### 5、AOP 代理(AOP Proxy) + +在Spring AOP 中有两种代理方式,JDK 动态代理和CGLib 代理。默认情况下,TargetObject 实现了 +接口时,则采用JDK 动态代理,例如,AServiceImpl;反之,采用CGLib 代理,例如,BServiceImpl。 +强制使用CGLib 代理需要将aop:config的proxy-target-class 属性设为true。 +通知(Advice)类型: + +### 6、前置通知(Before Advice) + +在某连接点(JoinPoint)之前执行的通知,但这个通知不能阻止连接点前的执行。ApplicationContext +中在aop:aspect里面使用aop:before元素进行声明。例如,TestAspect 中的doBefore 方法。 + +### 7、后置通知(After Advice) + +当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。ApplicationContext 中在 +aop:aspect里面使用aop:after元素进行声明。例如,ServiceAspect 中的returnAfter 方法,所 +以Teser 中调用UserService.delete 抛出异常时,returnAfter 方法仍然执行。 + +### 8、返回后通知(After Return Advice) + +在某连接点正常完成后执行的通知,不包括抛出异常的情况。ApplicationContext 中在aop:aspect +里面使用元素进行声明。 + +### 9、环绕通知(Around Advice) + +包围一个连接点的通知,类似Web 中Servlet 规范中的Filter 的doFilter 方法。可以在方法的调用前 +后完成自定义的行为, 也可以选择不执行。ApplicationContext 中在aop:aspect 里面使用 +aop:around元素进行声明。例如,ServiceAspect 中的around 方法。 + +### 10、异常通知(After Throwing Advice) + +在方法抛出异常退出时执行的通知。ApplicationContext 中在aop:aspect 里面使用 +aop:after-throwing元素进行声明。例如,ServiceAspect 中的returnThrow 方法。 +注:可以将多个通知应用到一个目标对象上,即可以将多个切面织入到同一目标对象。 +使用Spring AOP 可以基于两种方式,一种是比较方便和强大的注解方式,另一种则是中规中矩的xml +配置方式。 +先说注解,使用注解配置Spring AOP 总体分为两步,第一步是在xml 文件中声明激活自动扫描组件功 +能,同时激活自动代理功能(来测试AOP 的注解功能): + +配置方式。 +先说注解,使用注解配置Spring AOP 总体分为两步,第一步是在xml 文件中声明激活自动扫描组件功 +能,同时激活自动代理功能(来测试AOP 的注解功能) \ No newline at end of file diff --git a/second/week_07/87/di.assets/image-20200419231807510.png b/second/week_07/87/di.assets/image-20200419231807510.png new file mode 100644 index 0000000000000000000000000000000000000000..ba3da01a53797f86520e9368a6bc2d49bd845afc Binary files /dev/null and b/second/week_07/87/di.assets/image-20200419231807510.png differ diff --git a/second/week_07/87/di.md b/second/week_07/87/di.md new file mode 100644 index 0000000000000000000000000000000000000000..2c4367e6c9b9a9d52e4f0d0791e65bff3300e062 --- /dev/null +++ b/second/week_07/87/di.md @@ -0,0 +1,13 @@ +# DI时序 + +![image-20200419231807510](di.assets/image-20200419231807510.png) + +## 依赖注入发生的时间 + +当SpringIOC容器完成了Bean定义资源的定位、载入和解析注册以后,IOC容器中已经管理了Bean定义的相关数据。但此时IOC容器还没有对所管理的Bean进行依赖注入。依赖注入在以下两种情况发生: + 1.用户第一次调用getBean()方法时,IOC容器触发依赖注入 + 2.当用户在配置文件中将元素配置了 lazy-init=false 属性,即让容器在解析注册 Bean 定义时进行预实例化,触发依赖注入。 + +## 寻找Bean的入口 + +在BeanFactory中可以找到getBean()方法,具体实现在AbstractBeanFactory中,在getBean()方法中又调用doGetBean方法向IOC容器获取被管理的Bean,在BeanFactory中可以找到getBean()方法,具体实现在AbstractBeanFactory中,在getBean()方法中又调用doGetBean方法向IOC容器获取被管理的Bean,在doGetBean方法中会调用createBean方法,具体实现在AbstractAutowireCapableBeanFactory中。createBean方法中会调用doCreateBean方法,在doCreateBean方法中完成对Bean的依赖注入,最终由registerDisposableBeanIfNecessary方法注册完成依赖注入的bean。 \ No newline at end of file diff --git a/second/week_07/87/ioc.assets/image-20200419232033053.png b/second/week_07/87/ioc.assets/image-20200419232033053.png new file mode 100644 index 0000000000000000000000000000000000000000..459493f99cf3cd7bb80ffe1e52eb2151d2860c7d Binary files /dev/null and b/second/week_07/87/ioc.assets/image-20200419232033053.png differ diff --git a/second/week_07/87/ioc.assets/image-20200419232334282.png b/second/week_07/87/ioc.assets/image-20200419232334282.png new file mode 100644 index 0000000000000000000000000000000000000000..0885242fad77a3270417a60edaa96138ef9d9ec4 Binary files /dev/null and b/second/week_07/87/ioc.assets/image-20200419232334282.png differ diff --git a/second/week_07/87/ioc.md b/second/week_07/87/ioc.md new file mode 100644 index 0000000000000000000000000000000000000000..7e7520cccaf293c80164448cad5925d0b804b267 --- /dev/null +++ b/second/week_07/87/ioc.md @@ -0,0 +1,23 @@ +# IOC时序 + +![image-20200419232033053](ioc.assets/image-20200419232033053.png) + + + +![image-20200419232334282](ioc.assets/image-20200419232334282.png) + +## 什么是SpringIOC + +IOC(Inversion Of Control)控制反转,所谓控制反转,就是把我们代码中需要实现的对象的创建、依赖。反转给容器来实现。同时需要一种描述让容器知道需要创建的对象和对象之间的关系。即配置文件。 + + + +## IOC容器初始化的流程 + +容器启动的过程大概可以概括为三个步骤定位、加载和注册。即定位我们的配置文件,加载配置文件和根据配置文件进行注册 + + + +通过对其构造方法的跟踪,我们发现调用了refresh()方法,也就是我们时序图的起点。通过setConfigLocations方法我们也可以发现,配置文件通过字符串数组的形式进行传递。这里可以作为我们学习IOC容器的起点,即,定位配置文件。 + +根据时序图我们可以一步一步去学习认识IOC容器的初始化过程。 \ No newline at end of file diff --git a/second/week_07/87/mvc.assets/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0dvTmV3V2F5,size_16,color_FFFFFF,t_70.png b/second/week_07/87/mvc.assets/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0dvTmV3V2F5,size_16,color_FFFFFF,t_70.png new file mode 100644 index 0000000000000000000000000000000000000000..d22d3fb9d282857dd4dbf877751c914e6cbfc8ef Binary files /dev/null and b/second/week_07/87/mvc.assets/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0dvTmV3V2F5,size_16,color_FFFFFF,t_70.png differ diff --git a/second/week_07/87/mvc.md b/second/week_07/87/mvc.md new file mode 100644 index 0000000000000000000000000000000000000000..9fad73fe8dd8100e339b48415e8d8fc0f39cd56a --- /dev/null +++ b/second/week_07/87/mvc.md @@ -0,0 +1,23 @@ +# Spring mvc + +![img](mvc.assets/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0dvTmV3V2F5,size_16,color_FFFFFF,t_70.png) + +## SpringMVC工作机制 + +1.ApplicationContext初始化时用Map保存所有的url和controller对应关系。 +2.根据请求URL找到对应的controller,并从controller中找到对应的请求方法。 +3.Request参数绑定到方法的形参,执行方法处理请求,并返回结果视图。 + +## 初始化阶段 + +在DispatcherServlet的父类HttpServletBean中可以找到初始化的init()方法,在init()方法中又会调用FrameworkServlet类的initServletBean()方法,最终会调用refresh()方法,这部分代码最主要的逻辑是初始化IOC容器。 + +IOC容器初始化完成之后会调用DispatcherServlet类的onRefresh()方法,完成SpringMVC九大组件的初始化 + +## URL和controller建立关系 + +HandlerMapping的子类AbstractDetectingUrlHandlerMapping实现了initApplicationContext()方法,该方法的作用是通过获得ApplicationContext对象,得到该容器中所有的beanName,在对beanNames进行遍历得到bean上的URL,并由registerHandler方法进行注册。 + +## 运行调用阶段 + +当我们从浏览器端发出请求时,入口为DispatcherServlet的核心方法doService(),其中核心逻辑有doDispatch()实现。在doDispatch()方法中调用getHandler方法取得当前请求的controller,getHandler()方法会把request请求包装成HandlerExecutionChain对象。然后由HandlerExecutionChain对象进行后续操作,最终结果是返回ModelAndView视图。 \ No newline at end of file