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