假如一个班的同学要向老师交班费,但是都是通过班长把自己的钱转交给老师。这里,班长就是代理学生上交班费,班长就是学生的代理。
由程序员创建或特定工具自动生成源代码,也就是在编译时就已经将接口,被代理类,代理类等确定下来。在程序运行之前,代理类的.class文件就已经生成。
流程:
缺点:每个被代理类都要写一个针对的代理类。
代理类在程序运行时创建的代理方式被成为动态代理。动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法
若目标对象实现了接口,spring默认使用「JDK的动态代理」。
若目标对象没有实现任何接口,spring使用「CGLib动态代理」。
「1、jdk动态代理」
newProxyInstance()会返回一个实现了指定接口的代理对象,对该对象的所有方法调用都会转发给InvocationHandler.invoke()方法。理解上述代码需要对Java反射机制有一定了解。动态代理神奇的地方就是:
使用方法:代理类实现「InvocationHandler」,然后引用被代理类,并在构造方法里传入。然后重写invoke方法,为具体操作代码。然后通过
Proxy.newProxyInstance( getClass().getClassLoader(), new Class<?>[] {Hello.class}, // 2. 代理需要实现的接口,可以有多个
new LogInvocationHandler(new HelloImp()));// 3. 方法调用的实际处理者
Java动态代理是基于接口的,没有实现接口该类无法使用JDK代理,CGLIB登场。
「2、CGLIB动态代理」
CGLib采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法去技术拦截所有的父类方法的调用,并顺势织入横切逻辑。
目标对象:
//目标对象RealSubject,cglib不需要定义目标类的统一接口
public class RealSubject {
public void request() {
System.out.println("real subject execute request");
}
public void hello() {
System.out.println("hello");
}
}
代理对象:实现MethodInterceptor,重写intercept方法。
//代理对象
public class DemoMethodInterceptor implements MethodInterceptor{
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("before in cglib");
Object result = null;
try{
result = proxy.invokeSuper(obj, args);
}catch (Exception e){
System.out.println("get ex:"+e.getMessage());
throw e;
}finally {
System.out.println("after in cglib");
}
return result;
}
}
客户端调用:
//客户端
public class Client {
public static void main(String[] args){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(RealSubject.class);
enhancer.setCallback(new DemoMethodInterceptor());
// 此刻,realSubject不是单纯的目标类,而是增强过的目标类
RealSubject realSubject = (RealSubject) enhancer.create();
realSubject.hello();
realSubject.request()
}
}
也可以通过匿名的方式:
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(SampleClass.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("before method run...");
Object result = proxy.invokeSuper(obj, args);
System.out.println("after method run...");
return result;
}
});
SampleClass sample = (SampleClass) enhancer.create();
sample.test();
}
代理的原理可以参考:https://www.cnblogs.com/gonjan-blog/p/6685611.html
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有