反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)(转)2

 1反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)(转)2package sinosoft.dj.aop.proxyaop;

2

3importjava.lang.reflect.Method;

4

5publicinterfaceIOperation{

6/**

7*方法执行之前的操作

8*@parammethod

9*/

10voidstart(Methodmethod);

11/**

12*方法执行之后的操作

13*@parammethod

14*/

15voidend(Methodmethod);

16}

17

我们去写一个实现上面接口的类.我们把作他真正的操作者,如下面是日志操作者的一个类:

LoggerOperation.java

反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)(转)2package sinosoft.dj.aop.proxyaop;

importjava.lang.reflect.Method;

publicclassLoggerOperationimplementsIOperation{

publicvoidend(Methodmethod){

Logger.logging(Level.DEBUGE,method.getName()+"Methodend.");

}

publicvoidstart(Methodmethod){

Logger.logging(Level.INFO,method.getName()+"MethodStart!");

}

}

然后我们要改一下代理对象DynaProxyHello中的代码.如下:

 1反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)(转)2package sinosoft.dj.aop.proxyaop;

2

3importjava.lang.reflect.InvocationHandler;

4importjava.lang.reflect.Method;

5importjava.lang.reflect.Proxy;

6

7publicclassDynaProxyHelloimplementsInvocationHandler{

8/**

9*操作者

10*/

11privateObjectproxy;

12/**

13*要处理的对象(也就是我们要在方法的前后加上业务逻辑的对象,如例子中的Hello)

14*/

15privateObjectdelegate;

16

17/**

18*动态生成方法被处理过后的对象(写法固定)

19*

20*@paramdelegate

21*@paramproxy

22*@return

23*/

24publicObjectbind(Objectdelegate,Objectproxy){

25

26this.proxy=proxy;

27this.delegate=delegate;

28returnProxy.newProxyInstance(

29this.delegate.getClass().getClassLoader(),this.delegate

30.getClass().getInterfaces(),this);

31}

32/**

33*要处理的对象中的每个方法会被此方法送去JVM调用,也就是说,要处理的对象的方法只能通过此方法调用

34*此方法是动态的,不是手动调用的

35*/

36publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)

37throwsThrowable{

38Objectresult=null;

39try{

40//反射得到操作者的实例

41Classclazz=this.proxy.getClass();

42//反射得到操作者的Start方法

43Methodstart=clazz.getDeclaredMethod("start",

44newClass[]{Method.class});

45//反射执行start方法

46start.invoke(this.proxy,newObject[]{method});

47//执行要处理对象的原本方法

48result=method.invoke(this.delegate,args);

49//反射得到操作者的end方法

50Methodend=clazz.getDeclaredMethod("end",

51newClass[]{Method.class});

52//反射执行end方法

53end.invoke(this.proxy,newObject[]{method});

54

55}catch(Exceptione){

56e.printStackTrace();

57}

58returnresult;

59}

60

61}

62

然后我们把Test.java中的代码改一下.测试一下:

反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)(转)2package sinosoft.dj.aop.proxyaop;

publicclassTest{

publicstaticvoidmain(String[]args){

IHellohello=(IHello)newDynaProxyHello().bind(newHello(),newLoggerOperation());

hello.sayGoogBye("DoubleJ");

hello.sayHello("DoubleJ");

}

}

结果还是一样的吧.

如果你想在每个方法之前加上日志记录,而不在方法后加上日志记录.你就把LoggerOperation类改成如下:

 1反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)(转)2package sinosoft.dj.aop.proxyaop;

2

3importjava.lang.reflect.Method;

4

5publicclassLoggerOperationimplementsIOperation{

6

7publicvoidend(Methodmethod){

8//Logger.logging(Level.DEBUGE,method.getName()+"Methodend.");

9}

10

11publicvoidstart(Methodmethod){

12Logger.logging(Level.INFO,method.getName()+"MethodStart!");

13}

14

15}

16

运行一下.你就会发现,每个方法之后没有记录日志了.这样,我们就把代理者和操作者解藕了!

下面留一个问题给大家,如果我们不想让所有方法都被日志记录,我们应该怎么去解藕呢.?

我的想法是在代理对象的publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)方法里面加上个if(),对传进来的method的名字进行判断,判断的条件存在XML里面.这样我们就可以配置文件时行解藕了.如果有兴趣的朋友可以把操作者,被代理者,都通过配置文件进行配置,那么就可以写一个简单的SpringAOP框架了.

相关推荐