由代理模式到AOP的实例分析

内容来自书籍《架构探险-从零开始写Java Web框架》的整理

代理模式

首先看什么是代理?

代理的英文单词是Proxy,意思是不用你自己去做某件事,而是指派一位代理去帮你做,完成的效果和你自己做是一样的!比如单就上班打卡来说,你自己打卡和别人帮你打卡,对于打卡任务来说,结果是一样的!

 

代理有下面几种:

1.静态代理

代码综述:

一个业务接口,

一个业务接口的实现类,

一个代理类,

一个测试类

业务接口类(这个是后面实例要实现的一个公共接口):

1 package com.hm;
2 /**实际的主要的业务接口*/
3 public interface IHello {
4     void sayHello();
5 }

业务接口实现类(这个是后面实例要代理的一个公共业务实现类,并且后续会有改动)

1 package com.hm;
2 import org.springframework.stereotype.Component;
3 /**实际的实现了业务接口的实现类,也是将要被代理的目标类*/
4 public class HelloImpl implements IHello{
5     @Override
6     public void sayHello() {
7         System.out.println("hello in helloImpl");
8     }
9 }

业务实现类的静态代理类

 1 package com.hm.staticproxy;
 2 import com.hm.HelloImpl;
 3 import com.hm.IHello;
 4 /**
 5  * 这是一个代理类,但是都这样代理的话,代理类会越来越多
 6  */
 7 public class HelloProxy implements IHello{
 8 
 9     private HelloImpl helloImpl;
10     
11     public HelloProxy(){
12         this.helloImpl = new HelloImpl();
13     }
14     
15     @Override
16     public void sayHello() {
17         before();
18         this.helloImpl.sayHello();
19         after();
20     }
21     
22     public void before(){
23         System.out.println("before in helloProxy");
24     }
25     
26     public void after(){
27         System.out.println("after in helloProxy");
28     }
29 }

测试类(没有使用Junit):

1 package com.hm.staticproxy;
2 public class Test1 {
3     public static void main(String[] args) {
4         HelloProxy hp = new HelloProxy();
5         hp.sayHello();
6     }
7 }

可以看出静态代理类HelloProxy实现了和业务实现类HelloImpl实现了相同的接口IHello,在使用时,直接使用代理类就可以调用到实际的业务实现方法sayHello(),但是缺点也很明显,随着实现类变多,静态代理类也会随之变多,从而变成“类爆炸”。

2.JDK动态代理

使用JDK动态代理类会解决上述类爆炸的问题,只需要实现一个InvocationHandler接口就可以由JDK来生成你自己的代理类,比较方便。

JDK的动态代理类:

 1 package com.hm.dynamicproxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 import java.lang.reflect.Proxy;
 6 /**
 7  * JDK的动态代理类只有一个,一个类即完成了各种代理任务
 8  * 但是被代理类必须实现某个接口才行
 9  * @author Administrator
10  */
11 public class DynamicProxy implements InvocationHandler{
12 
13     private Object target;
14     
15     public DynamicProxy(Object target){
16         this.target = target;
17     }
18     
19     @Override
20     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
21         before();
22         Object result = method.invoke(target, args);
23         after();
24         return result;
25     }
26 
27     /**
28      * 这个是为了方便特意优化的一点
29      * 并且使用了泛型,不用每次强制转型
30      * 由这个方法的参数this.target.getClass().getInterfaces()可以看出
31      * 使用JDK的动态代理,被代理类必须实现最少一个接口
32      * 否则 无法实现代理,这时候需要使用CGLib
33      * @return
34      */
35     @SuppressWarnings("unchecked")
36     public <T> T getProxy(){
37         T t = (T) Proxy.newProxyInstance(
38                 this.target.getClass().getClassLoader(), 
39                 this.target.getClass().getInterfaces(), 
40                 this);
41         return t;
42         
43     }
44     
45     public void before(){
46         System.out.println("before in DynamicProxy");
47     }
48     
49     public void after(){
50         System.out.println("after in DynamicProxy");
51     }
52 }

测试类如下:

 1 package com.hm.dynamicproxy;
 2 
 3 import java.lang.reflect.Proxy;
 4 import com.hm.HelloImpl;
 5 import com.hm.IHello;
 6 
 7 public class Test2 {
 8     
 9     public static void main(String[] args) {
10         Test2 t2 = new Test2();
11         t2.test1();
12         System.out.println("----------------------------");
13         t2.test2();
14     }
15     
16     //这个是直接使用动态代理的方式,不过每次使用都要重复写出newInstance的过程,可以优化
17     public void test1(){
18         IHello hello = new HelloImpl();
19         DynamicProxy dp = new DynamicProxy(hello);
20         //需要强制转型
21         IHello helloProxy = (IHello) Proxy.newProxyInstance(
22                 hello.getClass().getClassLoader(), 
23                 hello.getClass().getInterfaces(), 
24                 dp);
25         helloProxy.sayHello();
26     }
27     
28     //这个也是直接使用动态代理的方式,不过生成代理的代码进行了优化
29     public void test2(){
30         IHello helloProxy = new DynamicProxy(new HelloImpl()).getProxy();
31         helloProxy.sayHello();
32     }
33 }

这样JDK动态代理类也实现了,并且只有一个代理类,很方便。但是,由这句代码

Proxy.newProxyInstance(

            this.target.getClass().getClassLoader(),

            this.target.getClass().getInterfaces(),

            this)

可以看出,第二个参数是返回业务类的父接口。那如果该业务类没有实现任何接口,JDK代理就无法使用了!

3.CGLib动态代理

Cglib是一个开源类库,这里使用它的话需要引入cglib.jar,可以自行下载

 

 1 package com.hm.cglibproxy;
 2 
 3 import java.lang.reflect.Method;
 4 
 5 import net.sf.cglib.proxy.Enhancer;
 6 import net.sf.cglib.proxy.MethodInterceptor;
 7 import net.sf.cglib.proxy.MethodProxy;
 8 /**
 9  * CGLib的代理不要求被代理类必须实现某接口,它是方法级别 的代理(拦截)
10  * @author Administrator
11  *
12  */
13 public class CGLibProxy implements MethodInterceptor{
14 
15     private static CGLibProxy instance;
16 
17     public static CGLibProxy getInstance(){
18         if(instance == null){
19             instance = new CGLibProxy();
20         }
21         return instance;
22     }
23     
24     @Override
25     public Object intercept(Object obj, Method method, Object[] args,
26             MethodProxy proxy) throws Throwable {
27         before();
28         Object result = proxy.invokeSuper(obj, args);
29         after();
30         return null;
31     }
32     
33     public <T> T getProxy(Class<T> clazz){
34         return (T) Enhancer.create(clazz, this);
35     }
36     
37     public void before(){
38         System.out.println("before in CGLibProxy");
39     }
40     
41     public void after(){
42         System.out.println("after in CGLibProxy");
43     }
44 }

测试类如下:

 1 package com.hm.cglibproxy;
 2 
 3 import com.hm.HelloImpl;
 4 import com.hm.IHello;
 5 
 6 public class Test3 {
 7 
 8     public static void main(String[] args) {
 9         test1();
10         System.out.println("--------------------------------");
11         test2();
12     }
13     
14     public static void test1(){
15         CGLibProxy cp = new CGLibProxy();
16         IHello helloProxy = cp.getProxy(HelloImpl.class);
17         helloProxy.sayHello();
18     }
19     public static void test2(){
20         IHello helloProxy = CGLibProxy.getInstance().getProxy(HelloImpl.class);
21         helloProxy.sayHello();
22     }
23     
24 }

至此三种代理的简单实现就讲完了!

Spring AOP

下面就来看看AOP吧

AOP面向切面编程,横切逻辑…等等就不多说了

这里主要分为:前置增强,后置增强,环绕增强,异常抛出增强

需要引入spring的jar包,我这里使用的是3.2版本

Jar如下:

 

为了方便我直接把spring3.2的所有jar包都引入了

还是来实现之前的业务接口IHello,代理之前的实现类HelloImpl吧

编程式:

前置增强

代码如下:

 1 package com.hm.spring;
 2 
 3 import java.lang.reflect.Method;
 4 import org.springframework.aop.MethodBeforeAdvice;
 5 /**
 6  * 前置增强
 7  * @author Administrator
 8  */
 9 public class HelloBeforeAdvice implements MethodBeforeAdvice {
10     @Override
11     public void before(Method arg0, Object[] arg1, Object arg2)
12             throws Throwable {
13         System.out.println("Before in HelloBeforeAdvice");
14     }
15 }

后置增强

 1 package com.hm.spring;
 2 
 3 import java.lang.reflect.Method;
 4 import org.springframework.aop.AfterReturningAdvice;
 5 /**
 6  * 后置增强
 7  * @author Administrator
 8  */
 9 public class HelloAfterAdvice implements AfterReturningAdvice{
10 
11     @Override
12     public void afterReturning(Object arg0, Method arg1, Object[] arg2,
13             Object arg3) throws Throwable {
14         System.out.println("After in HelloAfterAdvice");
15     }
16 }

测试类如下

(这个是后面spring的公共测试类,后面会改动,注意文件名)

 1 package com.hm.spring;
 2 
 3 import org.springframework.aop.framework.ProxyFactory;
 4 import com.hm.HelloImpl;
 5 import com.hm.IHello;
 6 
 7 public class ClientTest {
 8     public static void main(String[] args) {
 9         test1();
10         System.out.println("------------------");
11         test2();
12     }
13     
14     /**
15      * 前置增强
16      */
17     static void test1(){
18         //创建代理工厂
19         ProxyFactory pf = new ProxyFactory();
20         //射入目标类对象
21         pf.setTarget(new HelloImpl());
22         //添加前置增强
23         pf.addAdvice(new HelloBeforeAdvice());
24         //添加后置增强
25         pf.addAdvice(new HelloAfterAdvice());
26         //从方法中获取代理
27         IHello hello = (IHello) pf.getProxy();
28         //调用代理的方法
29         hello.sayHello();    
30 }
31     /**
32      * 后置增强
33      */
34     static void test2(){
35         ProxyFactory pf = new ProxyFactory();
36         pf.setTarget(new HelloImpl());
37         pf.addAdvice(new HelloBeforeAfterAdvice());
38         
39         IHello hello = (IHello) pf.getProxy();
40         hello.sayHello();
41     }
42 }

运行结果如下:

Before in HelloBeforeAdvice

hello in helloImpl

After in HelloAfterAdvice

------------------

before in HelloBeforeAfterAdvice

hello in helloImpl

after in HelloBeforeAfterAdvice

 

环绕增强

也可以定义一个增强类,同时实现这两个接口,这就形成了环绕增强

 1 package com.hm.spring;
 2 
 3 import java.lang.reflect.Method;
 4 import org.springframework.aop.AfterReturningAdvice;
 5 import org.springframework.aop.MethodBeforeAdvice;
 6 
 7 /**
 8  * 实现两个接口,共同完成环绕增强
 9  * @author Administrator
10  */
11 public class HelloBeforeAfterAdvice implements     MethodBeforeAdvice,AfterReturningAdvice{
12 
13     @Override
14     public void before(Method arg0, Object[] arg1, Object arg2)
15             throws Throwable {
16         System.out.println("before in HelloBeforeAfterAdvice");    
17     }
18     
19     @Override
20     public void afterReturning(Object arg0, Method arg1, Object[] arg2,
21             Object arg3) throws Throwable {
22         System.out.println("after in HelloBeforeAfterAdvice");    
23     }
24 }

同时也可以直接实现MethodInterceptor接口从而实现环绕增强,该接口不是spring提供的,而是AOP联盟写的,spring只是借用了它,故需要引入aopalliance.jar

如下:

 1 package com.hm.spring;
 2 
 3 import org.aopalliance.intercept.MethodInterceptor;
 4 import org.aopalliance.intercept.MethodInvocation;
 5 /**
 6  * 环绕增强
 7  * @author Administrator
 8  *
 9  */
10 public class HelloAroundAdvice implements MethodInterceptor{
11 
12     @Override
13     public Object invoke(MethodInvocation invocation) throws Throwable {
14         before();
15         Object result = invocation.proceed();
16         after();
17         return result;
18     }
19     
20     private void before(){
21         System.out.println("before in HelloAroundAdvice");
22     }
23     private void after(){
24         System.out.println("after in HelloAroundAdvice");
25     }
26 }

声明式

先提供一个spring的配置文件,beans.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3     xmlns:aop="http://www.springframework.org/schema/aop" 
 4     xmlns:context="http://www.springframework.org/schema/context"
 5     xmlns:p="http://www.springframework.org/schema/p"
 6     xmlns:tx="http://www.springframework.org/schema/tx" 
 7     xmlns:util="http://www.springframework.org/schema/util"
 8     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
 9         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd  
10         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd  
11         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd  
12         http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
13 
14     <!-- 自动包扫描 -->
15 <context:component-scan base-package="com.hm" />
16     
17     <bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
18         <!-- 需要代理的接口 ,注意是value-->
19         <property name="interfaces" value="com.hm.IHello"/>
20         <!-- 接口的实现类(目标类),注意是ref,指向一个bean -->
21         <property name="target" ref="HelloImpl"/>
22         <!-- 拦截器名称,即增强类的名称,spring bean的id -->
23         <property name="interceptorNames">
24             <list>
25                 <value>HelloAroundAdvice</value>
26 <value>HelloAfterAdvice</value>
27 <value>HelloBeforeAdvice</value>
28             </list>
29         </property>
30         <!--仅一个增强类时可以像如下配置--> 
31         <!--
32         <property name="interceptorNames" value="HelloAroundAdvice"/>
33          -->
34     </bean>
35 </beans>

主要注意的地方有:

1:

1         <!-- 接口的实现类(目标类),注意是ref,指向一个bean -->
2         <property name="target" ref="HelloImpl"/>

这里使用的是ref配置,所以HelloImpl是一个bean的名字,由于使用声明式配置,所以需要在公共业务实现类HelloImpl.java中添加一个注解,如下:

1 ……
2 @Component("HelloImpl")
3 public class HelloImpl implements IHello{
4 ……

2:

1         <!-- 拦截器名称,即增强类的名称,spring bean的id -->
2         <property name="interceptorNames">

这里同样是bean的名字,故需要在这上个增强类上添加注解:

1 @Component("HelloBeforeAdvice")
2 public class HelloBeforeAdvice implements MethodBeforeAdvice {
3 
4 
5 @Component("HelloAfterAdvice")
6 public class HelloAfterAdvice implements AfterReturningAdvice{
7 
8 @Component("HelloAroundAdvice")
9 public class HelloAroundAdvice implements MethodInterceptor{

这样在公共测试类ClientTest.java里面添加两个方法:

 1     /**
 2      * 环绕增强
 3      * 编程式
 4      */
 5     static void test3(){
 6         ProxyFactory pf = new ProxyFactory();
 7         pf.setTarget(new HelloImpl());
 8         pf.addAdvice(new HelloAroundAdvice());
 9         
10         IHello hello = (IHello) pf.getProxy();
11         hello.sayHello();
12     }
13     
14     /**
15      * 测试annotation版本的环绕增强
16      * 声明式
17      */
18     static void test4(){
19         ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
20         IHello hello = (IHello) context.getBean("helloProxy");
21         hello.sayHello();
22     }

然后在main方法里面执行,结果如下:

before in HelloAroundAdvice

Before in HelloBeforeAdvice

hello in helloImpl

After in HelloAfterAdvice

after in HelloAroundAdvice

 

可以看出相比前置和后置增强,环绕增强的结果在更前更后的位置

异常抛出增强

代码如下:

 1 package com.hm.spring;
 2 
 3 import java.lang.reflect.Method;
 4 import org.springframework.aop.ThrowsAdvice;
 5 import org.springframework.stereotype.Component;
 6 
 7 /**
 8  * 异常抛出增强
 9  * @author Administrator
10  *
11  */
12 @Component("HelloThrowAdvice")
13 public class HelloThrowAdvice implements ThrowsAdvice{
14     
15     public void afterThrowing(Method method,Object[] args,Object target,Exception e){
16         System.out.println("-------Throw Exception------");
17         System.out.println("Target Class: " + target.getClass().getName());
18         System.out.println("Method Name: " + method.getName());
19         System.out.println("Exception Message: " + e.getMessage());
20         System.out.println("---------------------------");
21     }
22 }

直接在beans.xml中配置该bean:

1 <bean id="helloThrowProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
2         <property name="interfaces" value="com.hm.IHello"/>
3         <property name="target" ref="HelloThrowsImpl"/>
4         <property name="interceptorNames" value="HelloThrowAdvice"/>
5     </bean>

在测试方法ClientTest.java中添加测试方法:

1 /**
2      * 测试异常抛出增强
3      */
4     static void test5(){
5         ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
6         IHello hello = (IHello) context.getBean("helloThrowProxy");
7         hello.sayHello();
8     }

在main方法中测试如下:

正是我们抛出的异常,已经被拦截(捕获,增强),拿到这些异常信息,则可以将其写到日志,持久化到数据库中。

引入增强

如果某个类实现了接口A,但是没有实现接口B,那么该类是否可以调用B中的方法呢?

通过引入增强则可以做到(只能说厉害)

 

首先在加入另外一个接口IApology

 1 package com.hm;
 2 
 3 /**
 4  * 不相关的接口
 5  * HelloImpl没有实现该接口,但是在ClientTest#test6()中却可以看到这样的调用
 6  * IApology apology = (IApology) helloImpl;
 7  * apology.saySorry();
 8  * 将HelloImpl转型为IApology即可以调用
 9  * @author Administrator
10  *
11  */
12 public interface IApology {
13 
14     void saySorry();
15 }

可以看到业务实现类HelloImpl并没有实现IApology接口,但是却想在程序运行的时候动态实现它,同时,如果HelloImpl业务很复杂,代码很多,并不想改动它的代码。怎么做呢?

借助一个spring的引入增强:

 1 package com.hm.spring;
 2 
 3 import org.aopalliance.intercept.MethodInvocation;
 4 import org.springframework.aop.support.DelegatingIntroductionInterceptor;
 5 import org.springframework.stereotype.Component;
 6 import com.hm.IApology;
 7 
 8 /**
 9  * 简述:
10  * 某个类实现了A接口,但是没有实现B接口,那么该类是否可以调用B接口的方法呢?
11  * 使用下面的代理即可
12  * 这是对类的增强-Introduction Advice
13  * @author Administrator
14  *
15  */
16 @Component("HelloIntroAdvice")
17 public class HelloIntroAdvice extends DelegatingIntroductionInterceptor implements IApology{
18 
19     public Object invoke(MethodInvocation invocation) throws Throwable{
20         return super.invoke(invocation);
21     }
22     
23     @Override
24     public void saySorry() {
25         System.out.println("sorry in HelloIntroAdvice");
26     }
27 }

在beans.xml中配置该bean:

1 <bean id="helloIntroProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
2         <property name="interfaces" value="com.hm.IApology"/>
3         <property name="target" ref="HelloImpl"/>
4         <property name="interceptorNames" value="HelloIntroAdvice"/>
5         <!-- 代理目标的类:true表示spring用CGLib做代理,false表示用JDK的动态代理 -->
6         <property name="proxyTargetClass" value="true"/>
7     </bean>

在ClientTest中添加测试方法:

 1     /**
 2      * 测试织入增强
 3      */
 4     static void test6(){
 5         ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
 6         //这里转为目标类,而不是它的接口类
 7         HelloImpl helloImpl = (HelloImpl) context.getBean("helloIntroProxy");
 8         helloImpl.sayHello();
 9         //将目标类强制 向上转型为IApology接口--"接口动态代理"
10         IApology apology = (IApology) helloImpl;
11         apology.saySorry();
12     }

在main方法中执行如下:

 

可以看到,最终通过强制类型转换实现了由helloImpl到apology的转化,从而调用到了saySorry()方法,真腻害!

测试拦截方法的数量:

测试上述方式会对公共接口的所有方法进行拦截:

修改接口,添加一个方法如下:

 1 package com.hm;
 2 
 3 /**
 4  * 实际的主要的业务接口
 5  * @author Administrator
 6 */
 7 public interface IHello {
 8     
 9     void sayHello();
10     
11     void sayHelloToo();
12 
13 }

仅仅在HelloImpl中实现该方法:

1     @Override
2     public void sayHelloToo() {
3         System.out.println("say hello too");
4     }

修改ClientTest中test1()方法

 1     static void test1(){
 2         //创建代理工厂
 3         ProxyFactory pf = new ProxyFactory();
 4         //射入目标类对象
 5         pf.setTarget(new HelloImpl());
 6         //添加前置增强
 7         pf.addAdvice(new HelloBeforeAdvice());
 8         //添加后置增强
 9         pf.addAdvice(new HelloAfterAdvice());
10         //从方法中获取代理
11         IHello hello = (IHello) pf.getProxy();
12         //调用代理的方法
13         hello.sayHello();
14         hello.sayHelloToo();
15     }

仅仅需要调用一下sayHelloToo方法即可

 

 

其他实现了IHello接口的实现类不要改动

此时HelloImpl实现了两个方法:sayHello()和sayHelloToo(),运行ClientTest中的test1()方法,结果如下:

Before in HelloBeforeAdvice

hello in helloImpl  (注意这个)

After in HelloAfterAdvice

Before in HelloBeforeAdvice

say hello too  (注意这个)

After in HelloAfterAdvice

可以看出,两个方法均被拦截(增强)了,故上述方式会对被代理类的所有接口实现类进行增强

 

还原回原来的IHello,HelloImpl,ClientTest代码吧

 

AOP切面

由上面的测试可以看出之前的代理都是对类级别的拦截,会拦截类里面的所有方法,而在实际情况中,一般只需要拦截特定的方法就行了,这里需要引入Advisor切面的概念了,它是将增强类与拦截匹配条件组合在一起,然后将这个切面配置到ProxyFactory中,从而生成代理。

 

既然需要拦截特定的方法,那么肯定需要提供一个拦截的条件,即什么样的方法可以被增强,Spring AOP提供了一些切面类,最常见的就是正则表达式的切面类,实例如下:

 

在HelloImpl中添加两个方法,一个以good开头,另一个不是,并且都不是接口中的方法,如下:

 1     /**
 2      * 该方法以good开头,故调用的时候会被拦截(增强),可以参见beans.xml的配置
 3      */
 4     public void goodMorning(){
 5         System.out.println("goodMorning in HelloImpl");
 6     }
 7     
 8     /**
 9      * 为了区分goodMorning方法,该方法不以good开头,故调用的时候不会被拦截(增强)
10      */
11     public void notGoodAfternoon(){
12         System.out.println("not goodMorning in HelloImpl");
13     }

在beans.xml中添加bean配置:

 1 <!-- 配置一个切面 -->
 2     <bean id="helloAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
 3         <property name="advice" ref="HelloAroundAdvice"></property>
 4         <property name="pattern" value="com.hm.HelloImpl.good.*"></property>
 5     </bean>
 6     
 7     <!-- 配置一个代理 -->
 8     <bean id="helloImplProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
 9         <property name="target" ref="HelloImpl"></property>
10         <property name="interceptorNames" value="helloAdvisor"></property>
11         <property name="ProxyTargetClass" value="true"></property>
12     </bean>

其中

<property name="pattern" value="com.hm.HelloImpl.good.*"></property>

com.hm.HellImpl.good.*表示匹配HelloImpl类中以good开头的方法,即拦截这些被匹配了的方法

 

在ClientTest中添加方法:

 1     /**
 2      * 测试自定义方法增强(拦截)
 3      */
 4     static void test7(){
 5         ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
 6         //这里转为目标类,而不是它的接口类
 7         HelloImpl helloImpl = (HelloImpl) context.getBean("helloImplProxy");
 8         helloImpl.sayHello();
 9         System.out.println("-------------------------");
10         //可以看出只有goodMorning方法被拦截(增强)了
11         helloImpl.goodMorning();
12         System.out.println("-------------------------");
13         helloImpl.notGoodAfternoon();
14     }

在main方法中运行:

hello in helloImpl

-------------------------

before in HelloAroundAdvice

goodMorning in HelloImpl

after in HelloAroundAdvice

-------------------------

not goodMorning in HelloImpl

 

可以看出只有以good开头的方法被拦截(增强)了

 

待续。。

 工程截图:

jar包截图:

posted on 2016-01-14 16:56  涩谷直子  阅读(233)  评论(0编辑  收藏  举报