`

反射实现 AOP 动态代理模式(2)

阅读更多

上面类中出现的Logger类和Level枚举还是和上一上例子的实现是一样的.这里就不贴出代码了.

让我们写一个Test类去测试一下.代码如下:
Test.java

 1package sinosoft.dj.aop.proxyaop;
 2
 3public class Test {
 4    public static void main(String[] args) {
 5        IHello hello = (IHello)new DynaProxyHello().bind(new Hello());
 6        hello.sayGoogBye("Double J");
 7        hello.sayHello("Double J");
 8        
 9    }

10}

11


运行输出的结果如下:

Tue Mar 04 21:24:03 CST 2008 sayGoogBye Method end .
Double J GoodBye!
2008-3-4 21:24:03 sayGoogBye Method Start!
Tue Mar 
04 21:24:03 CST 2008 sayHello Method end .
Hello Double J
2008-3-4 21:24:03 sayHello Method Start!


由于线程的关系,第二个方法的开始出现在第一个方法的结束之前.这不是我们所关注的!
从上面的例子我们看出.只要你是采用面向接口编程,那么,你的任何对象的方法执行之前要加上记录日志的操作都是可以的.他(DynaPoxyHello)自动去代理执行被代理对象(Hello)中的每一个方法,一个java.lang.reflect.InvocationHandler接口就把我们的代理对象和被代理对象解藕了.但是,我们又发现还有一个问题,这个DynaPoxyHello对象只能跟我们去在方法前后加上日志记录的操作.我们能不能把DynaPoxyHello对象和日志操作对象(Logger)解藕呢?
结果是肯定的.让我们来分析一下我们的需求.
我们要在被代理对象的方法前面或者后面去加上日志操作代码(或者是其它操作的代码),
那么,我们可以抽象出一个接口,这个接口里就只有两个方法,一个是在被代理对象要执行方法之前执行的方法,我们取名为start,第二个方法就是在被代理对象执行方法之后执行的方法,我们取名为end .接口定义如下 :

 1package sinosoft.dj.aop.proxyaop;
 2
 3import java.lang.reflect.Method;
 4
 5public interface IOperation {
 6    /** *//**
 7     * 方法执行之前的操作
 8     * @param method
 9     */

10    void start(Method method);
11    /** *//**
12     * 方法执行之后的操作
13     * @param method
14     */

15    void end(Method method);
16}

17


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

package sinosoft.dj.aop.proxyaop;

import java.lang.reflect.Method;

public class LoggerOperation implements IOperation {

    
public void end(Method method) {
        Logger.logging(Level.DEBUGE, method.getName() 
+ " Method end .");
    }


    
public void start(Method method) {
        Logger.logging(Level.INFO, method.getName() 
+ " Method Start!");
    }


}


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

 1package sinosoft.dj.aop.proxyaop;
 2
 3import java.lang.reflect.InvocationHandler;
 4import java.lang.reflect.Method;
 5import java.lang.reflect.Proxy;
 6
 7public class DynaProxyHello implements InvocationHandler {
 8    /** *//**
 9     * 操作者
10     */

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

15    private Object delegate;
16
17    /** *//**
18     * 动态生成方法被处理过后的对象 (写法固定)
19     * 
20     * @param delegate
21     * @param proxy
22     * @return
23     */

24    public Object bind(Object delegate,Object proxy) {
25        
26        this.proxy = proxy;
27        this.delegate = delegate;
28        return Proxy.newProxyInstance(
29                this.delegate.getClass().getClassLoader(), this.delegate
30                        .getClass().getInterfaces(), this);
31    }

32    /** *//**
33     * 要处理的对象中的每个方法会被此方法送去JVM调用,也就是说,要处理的对象的方法只能通过此方法调用
34     * 此方法是动态的,不是手动调用的
35     */

36    public Object invoke(Object proxy, Method method, Object[] args)
37            throws Throwable {
38        Object result = null;
39        try {
40            //反射得到操作者的实例
41            Class clazz = this.proxy.getClass();
42            //反射得到操作者的Start方法
43            Method start = clazz.getDeclaredMethod("start",
44                    new Class[] { Method.class });
45            //反射执行start方法
46            start.invoke(this.proxy, new Object[] { method });
47            //执行要处理对象的原本方法
48            result = method.invoke(this.delegate, args);
49//            反射得到操作者的end方法
50            Method end = clazz.getDeclaredMethod("end",
51                    new Class[] { Method.class });
52//            反射执行end方法
53            end.invoke(this.proxy, new Object[] { method });
54
55        }
 catch (Exception e) {
56            e.printStackTrace();
57        }

58        return result;
59    }

60
61}

62


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

package sinosoft.dj.aop.proxyaop;

public class Test {
    
public static void main(String[] args) {
        IHello hello 
= (IHello)new DynaProxyHello().bind(new Hello(),new LoggerOperation());
        hello.sayGoogBye(
"Double J");
        hello.sayHello(
"Double J");
        
    }

}

结果还是一样的吧.

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

 1package sinosoft.dj.aop.proxyaop;
 2
 3import java.lang.reflect.Method;
 4
 5public class LoggerOperation implements IOperation {
 6
 7    public void end(Method method) {
 8        //Logger.logging(Level.DEBUGE, method.getName() + " Method end .");
 9    }

10
11    public void start(Method method) {
12        Logger.logging(Level.INFO, method.getName() + " Method Start!");
13    }

14
15}

16


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

下面留一个问题给大家,如果我们不想让所有方法都被日志记录,我们应该怎么去解藕呢.?
我的想法是在代理对象的public Object invoke(Object proxy, Method method, Object[] args)方法里面加上个if(),对传进来的method的名字进行判断,判断的条件存在XML里面.这样我们就可以配置文件时行解藕了.如果有兴趣的朋友可以把操作者,被代理者,都通过配置文件进行配置 ,那么就可以写一个简单的SpringAOP框架了.

分享到:
评论

相关推荐

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

    AOP的意思就是面向切面编程。本文主要是通过梳理JDK中自带的反射机制,实现 AOP动态代理模式,这也是Spring AOP 的实现原理

    反射实现aop 动态代理

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

    反射实现 AOP 动态代理模式(Spring AOP 的实现 原理) - Java 例子 -

    NULL 博文链接:https://arne3166.iteye.com/blog/1046340

    复习反射利用反射机制和AOP代理模式

    reflection是一系列的API,用于表示或者处理当前JVM中的类,接口和对象. java.lang.reflect/java.lang.Class 在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

    spring 代理模式

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

    使用动态代理演示Spring的AOP编程原理

    为了说明Spring的AOP原理,本人使用代理模式中的动态代理完成演示AOP编程的原理的演示。相信,如果你耐心看完整个程序(几乎一行注释一行代码),那么你对Spring这个东西就不是觉得有什么神秘了! 阅读对象:凡是喜爱...

    利用Java的反射与代理实现IOC模式

    利用Java的反射与代理实现IOC模式 在Java中,其反射和动态代理机制极其强大,我们可以通过其反 射机制在运行时获取信息。而代理是一种基本的设计模式,它是一种为了提供额外的或不同的操作而插入到真 实对象中的...

    Java反射和动态代理实例

    几个Java反射和动态代理的小例子。可以学习如何通过Java的反射机制实例化对象、调用对象的方法、操作对象的私有成员变量、改变...可以学习Java的动态代理模式、学习Java工厂模式以及如何将工厂模式与属性文件相结合。

    通用动态代理链-为你的应用程序添加AOP

    这篇文章并不打算对AOP作深入的讨论,而准备把重点放在动态代理的一般链化上,从而使开发者可以用以框架驱动的方法去实现一些AOP概念。如果一个项目早已使用用某些现存的AOP框架,那么开发者不用再担心实现一个定制...

    Java动态代理简单应用

     代理模式是基本的设计模式之一,它是开发者为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象。这些操作通常涉及与“实际”对象的通信,因此代理通常充当着中间人的角色。  Java动态代理比代理...

    13Spring知识点1

    反射:动态代理设计模式 1.jdk 依赖接口 newProxyInstance方法 2.cglb 实现MethodInterceptor Aop 四种通知之前通

    SpringBoot的定时调用的加强工具,实现定时任务动态管理,后续加入可视化管理、调度日志、集群任务统一管理.zip

    springboot Spring框架是Java平台上的一种开源应用框架,提供具有控制反转...Spring框架具有面向切面编程(AOP)框架,SpringAOP框架基于代理模式,同时运行时可配置;AOP框架主要针对模块之间的交叉关注点进行模块化。

    JAVA Reflection(反射机制)

     代理模式  Java动态代理  简单的Aop实现  “程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。  尽管在这样...

    JAVA高并发高性能高可用高扩展架构视频教程

    揭开springAOP神秘面纱(动态代理) Mysql性能优化之索引优化 写实现Tomcat服务器 移动后台端框架设计 公司级框架原理解析 解密公司内部框架开发(打造属于自己的专属框架) 手写Tomca之深度解析动态资源请求原理 深度...

    springboot+vue实现简单的前后端分离.zip

    springboot Spring框架是Java平台上的一种开源应用框架,提供具有控制反转...Spring框架具有面向切面编程(AOP)框架,SpringAOP框架基于代理模式,同时运行时可配置;AOP框架主要针对模块之间的交叉关注点进行模块化。

    SpringBoot集成minio实现文件的上传,下载,获取列表,增加桶等的基本操作.zip

    springboot Spring框架是Java平台上的一种开源应用框架,提供具有控制反转...Spring框架具有面向切面编程(AOP)框架,SpringAOP框架基于代理模式,同时运行时可配置;AOP框架主要针对模块之间的交叉关注点进行模块化。

    基于 SpringBoot 多数据源 动态数据源 主从分离 快速启动器 支持分布式事务.zip

    springboot Spring框架是Java平台上的一种开源应用框架,提供具有控制反转...Spring框架具有面向切面编程(AOP)框架,SpringAOP框架基于代理模式,同时运行时可配置;AOP框架主要针对模块之间的交叉关注点进行模块化。

    asp.net知识库

    利用反射实现ASP.NET控件和数据实体之间的双向绑定,并且在客户端自动验证输入的内容是否合法 asp.net报表解决方法 SQLDMO类的使用 SQL过程自动C#封装,支持从表到基本存储过程生成 使用SQLDMO控制 SQL Server 使用SQL...

    SpringBoot集成常用开发中间件.zip

    Spring框架是Java平台上的一种...Spring框架具有面向切面编程(AOP)框架,SpringAOP框架基于代理模式,同时运行时可配置;AOP框架主要针对模块之间的交叉关注点进行模块化。Spring框架的AOP框架仅提供基本的AOP特性

Global site tag (gtag.js) - Google Analytics