今天面试美团的时候遇到了这个问题,当时只会实现接口的动态代理方式,后来上网查资料进行了一下浅显的总结(果然太菜了,虽然被据了n次,0offer但是也还得笑着学下去TAT)
jdk方式(实现接口)
jdk实现动态代理的方式是代理类和被代理类都实现了共同的接口,调用方法时,代理类proxy实质是通过InvocationHandler类中的invoke方法来进行调用,而invoke方法是通过反射来调用被代理类实际的方法。 代码框架如下:
/**
* 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);
}
// invoke方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 进行逻辑处理的函数
checkPopedom();
Object ret = null;
// 调用invoke方法
ret = method.invoke(targetObject, args);
return ret;
}
private void checkPopedom() {
// 模拟检查权限
System.out.println("检查权限:checkPopedom()!");
}
}
cglib方式(继承实现)
cglib方式的动态代理是利用asm开源包,将被代理对象的class文件加载进来,通过修改其子节码来生成子类来处理。 这种方式有几个重要的类
- Enhancer
- MethodeInterceptor 主要的方法拦截类,需要用户实现,其中需要实现intercept方法
public Object intercept(Object object, java.lang.reflect.Method method,
Object[] args, MethodProxy proxy) throws Throwable;
第一个参数是被代理的对象,第二个参数和第三个参数是拦截的方法和方法的参数。 3. MethodProxy Method类的代理类,可以方便实现对原对象方法对调用
代码框架:
/**
* CGlib动态代理类
*/
public class CGLibProxy implements MethodInterceptor {
// CGlib需要代理的目标对象
private Object targetObject;
public Object createProxyObject(Object obj) {
this.targetObject = obj;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(obj.getClass());
enhancer.setCallback(this);
Object proxyObj = enhancer.create();
return proxyObj;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object obj = null;
// 过滤方法
if ("addUser".equals(method.getName())) {
// 检查权限
checkPopedom();
}
obj = method.invoke(targetObject, args);
return obj;
}
private void checkPopedom() {
System.out.println("检查权限:checkPopedom()!");
}
}