JDK动态代理:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxy implements InvocationHandler {
private Object target;//目标类
public JdkProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 这里可以做增强,处理自己需求
System.out.println("before-新增的处理,干点啥呢???");
//对原始操作进行调用(反射)
Object result = method.invoke(target, args);
System.out.println("after-新增的处理,干完了!!!");
return result;
}
/**
* 创建代理类方法
* @return
*/
public Object createProxyObject(){
//目标类类加载器
ClassLoader loader=target.getClass().getClassLoader();
//目标类所实现的所有接口
Class<?>[] interfaces=target.getClass().getInterfaces();
Object object = Proxy.newProxyInstance(loader, interfaces, this);
return object;
}
}
CGLIB动态代理:
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxy implements MethodInterceptor {
public Object createProxyObject(Class clsss){
//1.Enhancer在内存中造出一个没有名称的动态类
Enhancer enhancer=new Enhancer();
//2.通过继承,先获取目标类对应的功能
enhancer.setSuperclass(clsss);
//3.增强,见intercept()
enhancer.setCallback(this);
return enhancer.create();
}
/**
* 拦截增强方法
* @param o 代理对象
* @param method 被拦截的方法
* @param objects 参数
* @param methodProxy cglib方法
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before-intercept干点啥");
Object result = methodProxy.invokeSuper(o,objects);
System.out.println("after-intercept干完了");
return result;
}
}
测试类:
public static void main(String[] args) {
MyInterfaceImpl myInterface = new MyInterfaceImpl();
JdkProxy jdkProxy = new JdkProxy(myInterface);
MyInterface myIn = (MyInterface) jdkProxy.createProxyObject();
System.out.println(myIn.doTest());
System.out.println("=====我是一个分割线==========");
CglibProxy cglibProxy = new CglibProxy();
MyInterface myInCglb = (MyInterface)cglibProxy.createProxyObject(MyInterfaceImpl.class);
System.out.println(myInCglb.doTest());
}
测试发现,代理类完成了被代理类的功能:
代理:
个人理解,就是一个代理类,拥有被代理类的功能,同时代理类可以添加一些自己的骚操作,然后向外提供服务。官方话语:Spring AOP 使用的动态代理,所谓的动态代理就是说 AOP 框架不会去修改字节码,而是在内存中临时为方法生成一个 AOP 对象,这个 AOP 对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
总结:
- 1.Spring默认使用jdk动态代理,如果目标类没有实现接口,那么 Spring AOP 会选择使用 CGLIB 来动态代理目标类。
- 2.JDK 动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK 动态代理的核心是 InvocationHandler 接口和 Proxy 类。
- 3.CGLIB 是一个代码生成的类库,可以在运行时动态的生成某个类的子类,CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final,那么它是无法使用 CGLIB 做动态代理的。
- 4.jdk创建对象的速度远大于cglib,cglib执行速度略大于jdk。因为cglib创建对象时需要操作字节码,生成的类会在Java的永久代中。如果动态代理操作过多,容易造成永久堆满,触发OutOfMemory异常。(解释1)
关注公众号,回复 面试 获取初级中级高级面试题。