Java之javassist实现自动代理-yellowcong

来源:互联网 发布:阿里云域名注册价格 编辑:程序博客网 时间:2024/06/01 08:41

Javaassist是通过操作class字节码文件来修改类的,如果需要Javaassist实现AOP,需要用到Javaassist的ProxyFactory、ProxyObject、MethodHandler三个类,通过这种方法就可以so easy的完成了,我们还可以自己写一个AOP的框架,通过Javassit同cglib一样,可以不依赖于接口的方式来实现代理操作

简单实现代码

这个简单实现,是直接使用的代码的api,没有做类的设计,只是简单将如何做Aop的主要代码写出来了,下面的我写了如何通过父类代理,来简化代理操作。

需要代理的对象

package com.yellowcong.test;public class TestDemo{    private String name;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public void say(String name) {        System.out.println("hello"+name);    }}

测试类

直接调用Javassist的api来做的,没有做封装的操作,我们可以自己建立一个拦截器,类似于JDK,然后调用Javassist的方法来解决动态代理,而且Javassist的功能强大,还可以动态编辑class文件

package com.yellowcong.test;import java.lang.reflect.Method;import javassist.util.proxy.MethodHandler;import javassist.util.proxy.ProxyFactory;import javassist.util.proxy.ProxyObject;/****作者:yellowcong*日期:2017/09/01*時間:8:23:56*描述:*/public class Demo8 {    public static void main(String[] args) throws Exception, IllegalAccessException {        //代理对象        ProxyFactory factory = new ProxyFactory();        //设定需要代理的类        factory.setSuperclass(TestDemo.class);        //创建class        Class<?> clazz = factory.createClass();        //实例化对象        TestDemo testDemo = (com.yellowcong.test.TestDemo) clazz.newInstance();        //设置代理对象        ((ProxyObject)testDemo).setHandler(new MethodHandler() {            /**             * @param obj 原来的对象              * @param method  这个是原来类的方法             * @param process JavaAssist获取的进程,是修改后的类方法             * @param args 参数             */            @Override            public Object invoke(Object obj, Method method, Method process, Object[] args) throws Throwable {                Object result = null;                System.out.println(method.getName()+"\t"+process.getName()+"执行前");                result = process.invoke(obj, args);                System.out.println("执行后");                return result;            }        });        testDemo.say("dou");    }}

自己实现AOP框架

定义代理类

代理类需要实现接口MethodHandler,里面有一个invoke的方法,同时,在getProxy类中,写了需要将代理类绑定到拦截器的类

/** * 定义接口 * @author zhangrw * @data 2017/09/01 */class MethodInterceptor implements MethodHandler{    private Object target ;    public MethodInterceptor(Object target) {        this.target = target ;    }    /**     * 执行代理方法     * @param obj     * @param method     * @param process     * @param args     * @return     * @throws Throwable     */    @Override    public Object invoke(Object obj, Method method, Method process, Object[] args) throws Throwable {        Object result = null;        System.out.println(method.getName()+"\t"+process.getName()+"执行前");        result = process.invoke(obj, args);        System.out.println("执行后");        return result;    }    /**     * 获取代理对象     * @return     * @throws Exception      * @throws InstantiationException      */    Object getProxy() throws Exception {        //代理对象        ProxyFactory factory = new ProxyFactory();        //设定需要代理的类        factory.setSuperclass(this.target.getClass());        //创建class        Class<?> clazz = factory.createClass();        //实例化对象 , 这个对象的字节类已经修改了, 是ProxyObject 的子类了        Object targetObj =  clazz.newInstance();        //设定代理的对象,我们设定为这个类,就可以了        ((ProxyObject)targetObj).setHandler(this);        return targetObj;    }}

子拦截器

定义的子拦截器,自需要覆写里面的invoke的方法就可以了,其他的方法默认就可以了

/** * 继承自共同的MethodInterceptor ,然后复写里面的invoke 方法 * @author zhangrw * @data 2017/09/01 */class MyInterceptor extends MethodInterceptor{    public MyInterceptor(Object target) {        super(target);    }    /**     * 执行代理方法     * @param obj     * @param method     * @param process     * @param args     * @return     * @throws Throwable     */    @Override    public Object invoke(Object obj, Method method, Method process, Object[] args) throws Throwable {        Object result = null;        System.out.println(method.getName()+"\t"+process.getName()+"执行前,extend");        result = process.invoke(obj, args);        System.out.println("执行后,Extend");        return result;    }}

调用代理对象

代理对象中,我们可以定义父类代理对象后,在使用子类代理对象,这样就可以节省一些重复代码的编写

/****作者:yellowcong*日期:2017/09/01*時間:8:23:56*描述:*/public class Demo9 {    public static void main(String[] args) throws Exception, IllegalAccessException {        MethodInterceptor parentProxy = new MethodInterceptor(new TestDemo());        TestDemo demo2 = (TestDemo) parentProxy.getProxy();        demo2.say("parent");        //获取代理对象        MyInterceptor proxy = new MyInterceptor(new TestDemo());        TestDemo demo = (TestDemo) proxy.getProxy();        demo.say("dobui");    }}
原创粉丝点击