文章目录
- 1.JDK动态代理
- 代码
- 代码结构:
- 总结
- 2.Cglib动态代理
- 代码
- 3.总结
1.JDK动态代理
首先,我们需要明白的就是在jdk动态代理当中,需要明白的就是,为什么会有这样一个代理,那是因为当需要代理的方法越来越多的时候,这个时候就会增大麻烦量,于是就引出了JDK的动态代理。
代码
首先是书写对应的接口,以及你需要完成的任务对应的实现类
subject.interface
package com.example.qhb.Jdk;
public interface Subject {
void request();
void hell0();
}
RealSubject.class
package com.example.qhb.Jdk;
import jdk.internal.loader.AbstractClassLoaderValue;
public class RealSubect implements Subject {
@Override
public void request() {
System.out.println("首先是发送对应的请求");
}
@Override
public void hell0() {
System.out.println("打一下招呼");
}
}
接下来就是对应的书写代理类了,首先,我们需要明白的就是,在这里是需要使用到jdk的动态代理,而这个代理的好处就是可以一次性地将方法写入到放法invoke()中去,这个方法又是存在于接口InvocationHandler中的,所以在这里我们需要使用代理类来对这个接口进行实现:
JdkProxySubject.class
package com.example.qhb.Jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class JdkProxySubject implements InvocationHandler {
//接下来就是引入需要执行定义的目标类
private RealSubect realSubect;
public JdkProxySubject(RealSubect realSubect) {
this.realSubect = realSubect;
}
/*
*invoke方法方法参数解析
*Object proxy:指被代理的对象。
*Method method:要调用的方法
*Object[] args:方法调用时所需要的参数
*InvocationHandler接口的子类可以看成代理的最终操作类。
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
Object result = null;
try {
//利用反射,动态地来反射方法,这就是动态代理和静态代理的区别
result = method.invoke(realSubect, args);//如果这里面是要进行invoke()单个的
//方法的话,仅仅只需要写上对应的方法
} catch (Exception e) {
System.out.println("ex:" + e.getMessage());
throw e;
} finally {
System.out.println("after");
}
return result;
}
}
接下来就是这个对应的Client,这里就是进行的测试
package ProxyDemoTest.Jdk;
import java.lang.reflect.Proxy;
/*首先,我们需要明白的就是在学习代理类的一个过程中,需要明白的就是需要
有客户端,还需要有接口
*/
public class Client {
public static void main(String[] args) {
/*
newProxyInstance方法参数解析
ClassLoader loader 方法参数解析
class<?>[] interfaces 得到全部的接口
InvocationHandler: 得到InvocationHandler接口的子类实例
*/
Subject subject=(Subject)Proxy.newProxyInstance(Client.class.getClassLoader(),new Class[]{Subject.class},
new JdkProxySubject(new RealSubect())) ;
subject.hell0();
subject.request();
}
}
这里面对应的就是主要的代理进行的一个过程,如果看不懂的话可以进行源码的品读,里面对应的就是首先是对这个class 进行加载,然后是对这个Subject接口进行加载,接下来就是对这个new JdkProxySubject(new RealSubject())进行的一个实现。
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h) {
Objects.requireNonNull(h);
final Class<?> caller = System.getSecurityManager() == null
? null
: Reflection.getCallerClass();
/*
* Look up or generate the designated proxy class and its constructor.
*/
Constructor<?> cons = getProxyConstructor(caller, loader, interfaces);
return newProxyInstance(caller, cons, h);
}
运行结果:
代码结构:
总结
我们在subject接口中新增加了一个hello()方法,然后在RealSubject中对hello()方法进行实现,但是在代理类中,我们不需要再去为hello方法再去写一个代理方法,而是通过反射调用目标对象的方法,来动态的生成代理类。
- 因为利用JdkProxySubject生成的代理类实现了接口,所以目标类中所有的方法在代理类中都有
- 生成的代理类的所有方法都拦截了目标类的所有的方法。而拦截器中invoke方法的内容正好就是代理类的各个方法的组成体
- 利用JDK代理方式必须有接口的存在。
2.Cglib动态代理
上文我们讲到了使用JDK的动态代理,但是当我们没有接口的时候,该怎么来进行呢,很简单,就是在对应的目标对象类中进行方法的编写
代码
package ProxyDemoTest.Cglib;
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();
}
}
package ProxyDemoTest.Cglib;
import java.lang.reflect.Method;
public class DemoMethodIntercepter implements MethodIntercepter{
@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;
}
}
package ProxyDemoTest.Cglib;
public class RealSubject {
public void request(){
System.out.println("发送一个请求");
}
public void hello(){
System.out.println("打个招呼");
}
}
这里面的思想和jdk动态代理的思想其实是相似的,不同之处在于cglib需要自己去下载一个包,进行引入
3.总结
总的来说,jdk动态代理和Cglib动态代理都是围绕着客户进行的,你需要进行方法的写入,一般而言都是方法较多的时候,然后就可以根据这样的方法类,引入invoke()这个方法进行实现,接下来需要做的就是这句关键词:
Subject subject=(Subject)Proxy.newProxyInstance(Client.class.getClassLoader(),new Class[]{Subject.class},
new JdkProxySubject(new RealSubect())) ;
HAHA,你学会(费)了吗,今天的学习就到这里吧,明怀我最近还是感觉有点点忙的,但还是不够自律,还是要认真完成任务,并且好好巩固知识才行呀,咱们加油!