第一种方式:JDK
原理:利用反射去调方法,Proxy这个类就是java.lang.reflect包下面的
-
拿到被代理类的class对象 --target
-
动态生成一个代理类CLASSA(class com.sun.proxy.$Proxy3),这类实现被代理类的所有接口
-
获取这个CLASSA的一个参数为InvocationHandler的构造方法
-
调用这个构造方法创建实例(这个就是代理对象);参数就是这个代理类WorkerProxy
大概的意思应该是这样的如下图,反射内容见
https://blog.youkuaiyun.com/u013523089/article/details/83999137
示例:
public class WorkerProxy implements InvocationHandler{
private Object target;
public WorkerProxy(Object target) {
// TODO Auto-generated constructor stub
this.target = target;
}
@Override
public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
// TODO Auto-generated method stub
System.out.println("员工盖房子");
return arg1.invoke(target, arg2);
}
}
测试类
IBuilder builder1 = (IBuilder) Proxy.newProxyInstance(IBuilder.class.getClassLoader(),
new Class[]{IBuilder.class},
new WorkerProxy(new Boss()));
builder1.buildHouse();
第二种方法,cglib
代理类通过字节码技术创建一个被代理类的子类实例
public class WorkerProxy implements MethodInterceptor{
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class<?> clazz) {
//设置需要创建子类的类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通过字节码技术,动态创建子类实例
return enhancer.create();
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
System.out.println("员工建房子");
//通过代理,调用父类的方法
return arg3.invokeSuper(arg0, arg2);
}
}
测试类
WorkerProxy worker = new WorkerProxy();
IBuilder builder = (IBuilder) worker.getProxy(Boss.class);
builder.buildHouse();
第三种:javassist
javassist.util.proxy
或使用org.apache.ibatis.javassist.util.proxy
public class WorkerProxy1 implements MethodHandler{
@Override
public Object invoke(Object arg0, Method arg1, Method arg2, Object[] arg3) throws Throwable {
// TODO Auto-generated method stub
System.out.println("PROXY");
return arg2.invoke(arg0, arg3);
}
}
测试代码
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(Boss.class);
Class<?> clazz = factory.createClass();
IBuilder testDemo = (IBuilder) clazz.newInstance();
((ProxyObject)testDemo).setHandler(new WorkerProxy1());
testDemo.buildHouse();