代理模式分为两种,静态代理 和 动态代理,静态代理简单易懂,对于新手来说便于理解,但实际运用到项目中代码量以及维护量都是非常大的,在企业级项目中不推荐使用这种方式,用于学习或者做毕设还是可以的,本文中只阐述动态代理模式,记录在这用于加深自身理解,同时希望能对您有所帮助。
JDK 动态代理
这种方式,只能对实现了接口的类生成代理,JDK动态代理采用委托机制,动态实现接口类,在动态生成的实现类中委托hanlder去调用原始实现类方法,但对于没有实现接口的类来说,就不适用了
/**
* 接口
*/
public interface Person {
void say();
}
/**
* 实现类
* 对于JDK 动态代理来说,只有 实现了接口的类才可以使用这种代理方式
*/
public class Children implements Person {
@Override
public void say() {
System.out.println("你好,世界。");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* JDK 动态代理
*/
public class JDKProxy implements InvocationHandler {
private Object targetObject;
public Object newProxy(Object targetObject){
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("练习发音");
// 这里切勿 使用 proxy 传参变量,会报错哟
// 在newProxy 方法 接收的参数targetObject,目的是在这里被运用
Object result = method.invoke(targetObject, args);
System.out.println("恭喜成功");
return result;
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
Person person = (Person) new JDKProxy().newProxy(new Children());
person.say();
// 报错信息:Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to Children
// at Main.main(Main.java:12)
// JDK 动态代理,动态生成的实现类 和 Children 并无关系,所以这里强转会报错
// 这种方式,采用委托机制,在动态生成的实现类里,委托Handler去调用原始实现类中的方法
/*
Children children = (Children) new JDKProxy().newProxy(new Children());
children.say();
*/
}
}
CGlib 动态代理
这种方式,不限制类是否实现了接口,相对于JDK 动态代理改进不少,同时又比JDK动态代理具备更高效的执行效率。
/**
* 没有实现接口的类,用于Cglib 动态代理
*/
public class User {
public void shopping(){
System.out.println("去海吉星采购");
}
}
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxy implements MethodInterceptor {
private Object targetObject;
public Object newProxy(Object targetObject){
this.targetObject = targetObject;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetObject.getClass());
enhancer.setCallback(this);
Object object = enhancer.create();
return object;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("开始处理……");
Object result = method.invoke(targetObject, args);
System.out.println("结束活动");
return result;
}
}
public class Main {
public static void main(String[] args) {
User user = (User) new CglibProxy().newProxy(new User());
user.shopping();
}
}
Cglib方式,上面的代码如要运行成功,还需 额外引入 cglib-2.2.jar 和 asm-3.1jar,这两个包,特别注意的事,cglib-3.1.jar,引入会报错,由于时间关系,没有特别深入的了解原因,换成 2.2版本即可