做网站挣钱经历,热门职业培训班,电脑网络连接不上怎么解决,成安网站建设1、代理模式的理解#xff1a;不修改A对象的代码的基础上#xff0c;对A代码块进行拓展。通过创建ProxyA代理对象#xff0c;拓展A对象并调用A对象的核心功能#xff1b;
即#xff1a;不修改对象的源码基础上#xff0c;创建代理对象#xff0c;进行功能的附加和增强不修改A对象的代码的基础上对A代码块进行拓展。通过创建ProxyA代理对象拓展A对象并调用A对象的核心功能
即不修改对象的源码基础上创建代理对象进行功能的附加和增强
2、代理的分类1静态代理2动态代理jdk,cglib
3、静态代理在编译的过程中就已经将代理对象、被代理对象、接口确定下来了class文件已经生成了
实现步骤 1、定义一个接口及其实现类 2、创建一个代理类同样实现这个接口 3、将目标对象注注入进代理类然后在代理类的对应方法调用目标类中的对应方法。
3.1定义一个接口及方法ParentPrint
package com.example.demo.proxy;public interface ParentPrint {void print(String content);
}3.2定义一个被代理的类并实现接口ParentPrint,其中print方法就是我们需要代理的核心方法
package com.example.demo.proxy;public class Printer implements ParentPrint {Overridepublic void print(String content) {System.out.println(content);}
}3.3定义代理类构造一个有参数的构造器并重写print方法其中通过传入的参数调用被代理对象的print方法。
package com.example.demo.proxy;/*
1、首先需要代理类ProxyStaticPrinter和被代理类Printer同时实现一个共同的接口
2、代理类ProxyStaticPrinter需要在构造方法中注入接口定义对象并重写代理的方法print前置后置处理,在其中加入注入对象的print方法
3、实例化代理对象ProxyStaticPrinter实例化被代理对象Printer
4、将被代理对象通过参数注入到代理对象ProxyStaticPrinter有参构造器中
5、代理对象调用处理过的方法
*/
public class ProxyStaticPrinter implements ParentPrint {private ParentPrint parentPrint;public ProxyStaticPrinter(ParentPrint parentPrint) {this.parentPrint parentPrint;}Overridepublic void print(String content) {System.out.println(前置操作);parentPrint.print(content);System.out.println(后置操作);}}
3.4测试定义一个代理对象将代理对象通过参数传入被代理的对象中 //测试public static void main(String[] args) {ParentPrint parentPrint new Printer();ParentPrint ProxyParentPrint new ProxyStaticPrinter(parentPrint);ProxyParentPrint.print(测试);}
运行 3.5总结
将目标对象注注入进代理类然后在代理类的对应方法调用目标类中的对应方法。这样的话我们就可以通过代理类屏蔽对目标对象的访问
优点被代理类无需实现接口缺点只能代理这个类要想代理其他类要想代理其他类需要写新的代理方法。
4、动态代理动态代理包含了jdk动态代理和cglib动态代理
4.1jkd动态代理
实现步骤 1、定义一个接口及其实现类 2、自定义 InvocationHandler 并重写invoke方法在 invoke 方法中我们会调用原生方法被代理类的方法并自定义一些处理逻辑 3、通过 Proxy.newProxyInstance(ClassLoader loader,Class?[] interfaces,InvocationHandler h) 方法创建代理对象
4.1.1定义一个接口
package com.example.demo.proxy;public interface ParentPrint {void print(String content);
}4.1.2定义一个接口及方法ParentPrint
package com.example.demo.proxy;public interface ParentPrint {void print(String content);
}4.1.3定义一个被代理的类并实现接口ParentPrint,其中print方法就是我们需要代理的核心方法
package com.example.demo.proxy;public class Printer implements ParentPrint {Overridepublic void print(String content) {System.out.println(content);}
}4.1.4定义一个代理类ProxyJdkPrinter并实现InvocationHandler实现invoke方法最终调用method.invoke(parentPrint,args)
注意该Proxy类中是静态方法且接收的三个参数依次为
ClassLoader loader指定当前目标对象使用类加载器获取加载器的方法是固定的。 Class?[] interfaces目标对象实现的接口的类型使用泛型方式确认类型。 InvocationHandler事件处理执行目标对象的方法时会触发事件处理器的方法会把当前执行目标对象的方法作为参数传入。
package com.example.demo.proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*jdk动态代理前提目标类必须有父接口接口ParentPrint,目标类Printer
1、创建ProxyJdkPrinter类继承接口InvocationHandler创建代理类的调用处理程序
2、同样引入代理类的参数对象private ParentPrint parentPrint;
3、实现invoke方法最终调用method.invoke(parentPrint,args)
4、测试
实例化代理类p1
将p1放入代理类ProxyJdkPrinter
通过Proxy类的WuDaInvocationHandler方法创建代理对象
代理对象调用被代理的方法
* */
public class ProxyJdkPrinter implements InvocationHandler {private ParentPrint parentPrint;public ProxyJdkPrinter(ParentPrint parentPrint) {this.parentPrint parentPrint;}Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {String name method.getName();if(name.equals(print)){System.out.println(jdk增加操作);}return method.invoke(parentPrint,args);}}
4.1.5测试invoke() 方法: 当我们的动态代理对象调用原生方法的时候最终实际上调用到的是 invoke() 方法然后 invoke() 方法代替我们去调用了被代理对象的原生方法。 public static void main(String[] args) {ParentPrint p1 new Printer();ProxyJdkPrinter proxyJdkPrinter new ProxyJdkPrinter(p1);//newProxyInstance:创建代理实例对象//三个参数//1、 目标类的类加载器 2、目标类的父接口 3、handlerParentPrint proxyPrint (ParentPrint)Proxy.newProxyInstance(p1.getClass().getClassLoader(), p1.getClass().getInterfaces(), proxyJdkPrinter);proxyPrint.print(测试);}
运行 4.1.6总结
通过java提供的Proxy类帮我们创建代理对象基于接口的动态代理需要利用JDK中的API在JVM内存中动态的构建Proxy对象 优点可以生成所有实现接口的代理对象 缺点JDK反射生成代理必须面向接口, 这是由Proxy的内部实现决定的。生成代理的方法中你必须指定实现类的接口它根据这个接口来实现代理类生成的所实现的接口。 4.2cglib动态代理当目标没有实现类的时候可以使用
实现步骤
1、定义一个类 2、自定义 MethodInterceptor 并重写 intercept 方法intercept 用于拦截增强被代理类的方法和 JDK 动态代理中的 invoke 方法类似 3、通过 Enhancer 类的 create()创建代理类
4.2.1)定义一个被代理类Printer
package com.example.demo.proxy;public class Printer1 {public void print(String content) {System.out.println(content);}
}4.2.2)定义一个代理类ProxyCglibPrinter并实现MethodInterceptor
package com.example.demo.proxy;import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*cglib动态代理目标对象不需要实现接口
实现MethodInterceptor 接口在调用目标对象的方法时就可以实现在调用方法之前、调用方法过程中、调用方法之后对其进行控制。
1.创建目标对象target
2.创建interceptor对象
3.创建Enhancer对象它以目标类和interceptor作为原料生产出代理对象
4、enhancer设置参数setSuperclasssetCallback
5、创建代理类proxy,调用需要代理的方法
* */
public class ProxyCglibPrinter implements MethodInterceptor {Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {String name method.getName();if(name.equals(print)){System.out.println(cglib增加操作);}methodProxy.invokeSuper(o,objects);return null;}}
4.2.3测试 public static void main(String[] args) {Printer1 target new Printer1();ProxyCglibPrinter interceptor new ProxyCglibPrinter();Enhancer enhancer new Enhancer();enhancer.setSuperclass(target.getClass());enhancer.setCallback(interceptor);Printer1 proxy (Printer1)enhancer.create();proxy.print(测试);}
运行 4.2.4)总结
无需代理类实现接口使用Cblib中的Enhancer来生成代理对象子类并实现MethodInterceptor中的intercept方法在此方法中可以实现增强功能。
如果目标对象需要实现接口则使用JDK代理。 如果目标对象不需要实现接口则使用Cglib代理。
5、综上所述再次总结
静态代理
jdk动态代理
cglib动态代理