Java之javassist实现自动代理-yellowcong

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");


    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狂飙的yellowcong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值