目录
先说说这篇文章看完你能学习到什么吧
1:代理是什么鬼,2:代理分类,3:为什么要使用代理,4:我们怎么如何代理接口和子类。5:敲黑板
1:代理是什么鬼
代理就是代为处理方法,增强类的功能,本质就是对类的方法增强(advice),简单来说就是中间商。比如你是厂家,你不想自己卖东西,那么这时候你可以招收代理帮你卖,他可以适当提高价格,卖点中间价,这就是代理。
2:代理分类
按生成代理的方式来分,是分为传统的静态代理和动态代理
a:静态代理:传统的代理方式,编译期间已经确定了代理类的代码,简单来说,项目代码中就已经有被代理类(非接口类)和代理类的代码了。
b:动态代理:代理类,编译期间还没生成,而是通过Java虚拟机来去动态的生成代理类,需要的时候动态创建。动态代理又有两种方式-------接口的动态代理,类的动态代理。
3:为什么要用代理
回答这个问题前,先问你是否有用过用过Spring-validation这个框架,这个就是用spring-aop进行参数检验,而spring-aop本质就是cglib的动态代理的方式。所以你知道为什么要用代理了,就是能就匹配的方式进行处理增强。从而增强代码模块,也可以实现代码的解耦和美观。
4:我们怎么如何代理接口和子类
这个部分,我们分为静态代理和动态代理的来讲解。
1->环境(自己去建一个maven项目)
【jdk8】,【maven3.5】,【intellj idea2018】
2->静态代理
a:新建个被代理接口类
public interface Subject { public void resolve(); }
b:新建个被代理类
public class BeStaticProxyObject implements Subject{ public void resolve() { System.out.println("我是被“静态代理”的方法,我在终于开始执行了"); } }
c:新建代理类
public class StaticProxy implements Subject{ private BeStaticProxyObject beStaticProxyObject; public StaticProxy(BeStaticProxyObject beStaticProxyObject) { this.beStaticProxyObject = beStaticProxyObject; } public void resolve() { System.out.println("我是“静态代理”的方法,我在“被代理的方法”之前执行"); beStaticProxyObject.resolve(); } }
d:启动运行类
public class MainClass { public static void main(String args[]){ BeStaticProxyObject beStaticProxyObject = new BeStaticProxyObject(); StaticProxy staticProxy = new StaticProxy(beStaticProxyObject); staticProxy.resolve(); } }
3->动态代理(接口的动态代理)
a:新建个被代理接口类
public interface Subject { public void resolve(); }
b:新建个被代理类
public class BeStaticProxyObject implements Subject{ public void resolve() { System.out.println("我是被“静态代理”的方法,我在终于开始执行了"); } }
c:新建代理类
public class ProxyInteface implements InvocationHandler { BeStaticProxyObject beStaticProxyObject; public ProxyInteface(BeStaticProxyObject beStaticProxyObject) { this.beStaticProxyObject = beStaticProxyObject; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("我是“动态代理接口”的方法,你想执行被代理的方法,必须经过我拦截和处理"); return method.invoke(this.beStaticProxyObject, args); } }
d:启动运行类
public class MainClass { public static void main(String args[]){ BeStaticProxyObject beStaticProxyObject = new BeStaticProxyObject(); StaticProxy staticProxy = new StaticProxy(beStaticProxyObject); staticProxy.resolve(); ProxyInteface proxyInteface = new ProxyInteface(beStaticProxyObject); Subject subject = (Subject)Proxy.newProxyInstance(beStaticProxyObject.getClass().getClassLoader(), beStaticProxyObject.getClass().getInterfaces(), proxyInteface); subject.resolve(); }
4->动态代理(类的动态代理)
a:pom.xml导入cglib库
<dependencies> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency> </dependencies>
b:新建个接口,用来处理代理方法,也方便lamd表示
public interface ProxyMethodInterceptor { public Object intercept(Object obj, Method method, Object[] args) throws Throwable; }
c:新建个被代理类
public class BeStaticProxyObject{ public void resolve() { System.out.println("我是被“代理”的方法,我在终于开始执行了"); } }
d:新建个代理工厂
public class ProxyFactory implements MethodInterceptor { private Object target; private ProxyMethodInterceptor interceptor; private ProxyFactory(Object target, ProxyMethodInterceptor interceptor) { this.target = target; this.interceptor = interceptor; } @SuppressWarnings("unchecked") public static <T> T getProxyInstance(Object target, ProxyMethodInterceptor interceptor) { ProxyFactory pf = new ProxyFactory(target, interceptor); Enhancer en = new Enhancer(); en.setSuperclass(target.getClass()); en.setCallback(pf); return (T)en.create(); } public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { return interceptor.intercept(target, method, args); } }
e:启动运行类
public class MainClass { public static void main(String args[]){ BeStaticProxyObject beStaticProxyObject = new BeStaticProxyObject(); StaticProxy staticProxy = new StaticProxy(beStaticProxyObject); staticProxy.resolve(); ProxyInteface proxyInteface = new ProxyInteface(beStaticProxyObject); Subject subject = (Subject)Proxy.newProxyInstance(beStaticProxyObject.getClass().getClassLoader(), beStaticProxyObject.getClass().getInterfaces(), proxyInteface); subject.resolve(); BeStaticProxyObject proxyInstance = ProxyFactory.getProxyInstance(beStaticProxyObject, (Object obj, Method method, Object[] nowArgs) -> { System.out.println("我是“动态代理cglib”的方法,你想执行被代理的方法,必须经过我拦截和处理"); return method.invoke(obj, nowArgs); }); proxyInstance.resolve(); } }
5:敲黑板
1:动态代理接口是通过什么原理实现代理的?
答:动态代理接口是用jdk本身的Proxy类去实现创建个代理对象,这种方式可以返回接口。我们通过接口调用方法,就可以完美实现接口的代理
2:动态代理类是通过什么原理实现代理的?
答:动态代理类是通过cglib库的Enhancer 底层的字节码技术ASM进行类的代理生成,并返回该类。通过类的调用方法,就可以对方法进行拦截和处理。
3:动态代理类的cglib目前有哪些地方有用?
答:我们熟悉的Hibernate就是采用这个。
4:你代理工厂那边的<T> T是啥意思,还有cglib的Enhancer怎么生成代理的?
答:上面的T其实就是泛型,我把他作为返回值出去,是方便你调用那个静态方法时候,不需要重新自己再转类型,而只需要通过你接受的变量类型推导出泛型T的类型,并自己强转。enhancer这个类想要创建代理类,只需要设置该代理的超类,也就是父类,即被代理那个类,en.setSuperclass(target.getClass()); 然后再设置代理方法的拦截器MethodInterceptor ,这个拦截器用来处理代理方法,本文自定义了类去实现这个接口,en.setCallback(pf); 最后进行create就行,return (T)en.create();
5:动态代理的两种方式,jdk的proxy和cglib的enhancer我们是不是可以理解创建的代理类型为接口和创建代理类型为父类的代理。就是接口和继承的关系对不?
答:没错的,你可以这么理解