@@ -148,8 +148,90 @@ helloWorldService.helloWorld();
148148
149149# 第二部分:AOP及实现
150150
151+ AOP相关概念较多,我不会一一列举,但是会在每一步对概念做一点解释。
152+
153+ AOP分为配置(Pointcut,Advice),织入(Weave)两部分工作,当然还有一部分是将AOP整合到整个容器的生命周期中。
154+
151155## 7.step7-使用JDK动态代理实现AOP织入
152156 git checkout step-7-method-interceptor-by-jdk-dynamic-proxy
157+
158+ 织入(weave)相对简单,我们先从它开始。Spring AOP的织入点是` AopProxy ` ,它包含一个方法` Object getProxy() ` 来获取代理后的对象。
159+
160+ 在Spring AOP中,我觉得最重要的两个角色,就是我们熟悉的` MethodInterceptor ` 和` MethodInvocation ` (这两个角色都是AOP联盟的标准),它们分别对应AOP中两个基本角色:` Advice ` 和` Joinpoint ` 。Advice定义了在切点指定的逻辑,而Joinpoint则代表切点。
161+
162+ ``` java
163+ public interface MethodInterceptor extends Interceptor {
164+
165+ Object invoke (MethodInvocation invocation ) throws Throwable ;
166+ }
167+ ```
168+
169+ Spring的AOP只支持方法级别的调用,所以其实在AopProxy里,我们只需要将MethodInterceptor放入对象的方法调用即可。
170+
171+ 我们称被代理对象为` TargetSource ` ,而` AdvisedSupport ` 就是保存TargetSource和MethodInterceptor的元数据对象。这一步我们先实现一个基于JDK动态代理的` JdkDynamicAopProxy ` ,它可以对接口进行代理。于是我们就有了基本的织入功能。
172+
173+ ``` java
174+ @Test
175+ public void testInterceptor() throws Exception {
176+ // --------- helloWorldService without AOP
177+ ApplicationContext applicationContext = new ClassPathXmlApplicationContext (" tinyioc.xml" );
178+ HelloWorldService helloWorldService = (HelloWorldService ) applicationContext. getBean(" helloWorldService" );
179+ helloWorldService. helloWorld();
180+
181+ // --------- helloWorldService with AOP
182+ // 1. 设置被代理对象(Joinpoint)
183+ AdvisedSupport advisedSupport = new AdvisedSupport ();
184+ TargetSource targetSource = new TargetSource (helloWorldService, HelloWorldServiceImpl . class,
185+ HelloWorldService . class);
186+ advisedSupport. setTargetSource(targetSource);
187+
188+ // 2. 设置拦截器(Advice)
189+ TimerInterceptor timerInterceptor = new TimerInterceptor ();
190+ advisedSupport. setMethodInterceptor(timerInterceptor);
191+
192+ // 3. 创建代理(Proxy)
193+ JdkDynamicAopProxy jdkDynamicAopProxy = new JdkDynamicAopProxy (advisedSupport);
194+ HelloWorldService helloWorldServiceProxy = (HelloWorldService ) jdkDynamicAopProxy. getProxy();
195+
196+ // 4. 基于AOP的调用
197+ helloWorldServiceProxy. helloWorld();
198+
199+ }
200+ ```
201+
153202
203+ ## 8.step8-使用AspectJ管理切面
204+ git checkout step-8-invite-pointcut-and-aspectj
205+
206+ 完成了织入之后,我们要考虑另外一个问题:对什么类以及什么方法进行AOP?对于“在哪切”这一问题的定义,我们又叫做“Pointcut”。Spring中关于Pointcut包含两个角色:` ClassFilter ` 和` MethodMatcher ` ,分别是对类和方法做匹配。Pointcut有很多种定义方法,例如类名匹配、正则匹配等,但是应用比较广泛的应该是和` AspectJ ` 表达式的方式。
207+
208+ ` AspectJ ` 是一个“对Java的AOP增强”。它最早是其实是一门语言,我们跟写Java代码一样写它,然后静态编译之后,就有了AOP的功能。下面是一段AspectJ代码:
209+
210+ ``` java
211+ aspect PointObserving {
212+ private Vector Point . observers = new Vector ();
213+
214+ public static void addObserver(Point p, Screen s) {
215+ p. observers. add(s);
216+ }
217+ public static void removeObserver(Point p, Screen s) {
218+ p. observers. remove(s);
219+ }
220+ ...
221+ }
222+ ```
223+
224+ 这种方式无疑太重了,为了AOP,还要适应一种语言?所以现在使用也不多,但是它的` Pointcut ` 表达式被Spring借鉴了过来。于是我们实现了一个` AspectJExpressionPointcut ` :
225+
226+ ``` java
227+ @Test
228+ public void testMethodInterceptor() throws Exception {
229+ String expression = " execution(* us.codecraft.tinyioc.*.*(..))" ;
230+ AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut ();
231+ aspectJExpressionPointcut. setExpression(expression);
232+ boolean matches = aspectJExpressionPointcut. getMethodMatcher(). matches(HelloWorldServiceImpl . class. getDeclaredMethod(" helloWorld" ),HelloWorldServiceImpl . class);
233+ Assert . assertTrue(matches);
234+ }
235+ ```
154236
155- ## 8.step8-使用Aspectj管理切面
237+ ## 9.
0 commit comments