1、什么是代理模式
为其他对象提供一种代理以控制对这个对象的访问。
2、为什么使用代理模式
开闭原则,增加功能。
3、代理模式实现原理
代理模式主要包含三个角色:抽象主题角色Subject,被代理角色Proxied,代 理类proxy

4、代理模式应用场景
SpringAOP、日志收集、权限控制、过滤器、RPC远程调用
5、代理模式的创建方式
静态代理和动态代理
理解:自己手写代理类就是静态代理
6、静态代理(两种实现方式)
//基于接口实现方式public interface OrderService {void order();}public class OrderServiceImpl implements OrderService {public void order() {System.out.println("用户下单操作..");}}public class OrderServiceProxy implements OrderService {/*** 代理对象*/private OrderService proxiedOrderService;public OrderServiceProxy( OrderService orderService) {this.proxiedOrderService=orderService;}public void order() {System.out.println("日志收集开始..");proxiedOrderService.order();System.out.println("日志收集结束..");}}public class ClientTest {public static void main(String[] args) {OrderService orderService = new OrderServiceProxy(new OrderServiceImpl());orderService.order();}}//接口继承方式实现public class OrderServiceProxy extends OrderServiceImpl {public void order() {System.out.println("日志收集开始..");super.order();System.out.println("日志收集结束..");}}public class ClientTest {public static void main(String[] args) {OrderService orderService = new OrderServiceProxy();orderService.order();}}
7、动态代理
JDK动态代理:
JDK动态代理所代理的类定要实现某个接口,其底层应用的是java反射实 现的;
创建的步骤:
1、创建被代理的接口和类;
2、实现InvocationHandler接口,对目标接口中声明的所有方 法进行统一处理;
3、调用Proxy的静态方法,创建代理类并生成相应的代理对 象。
public interface OrderService {void order();}public class OrderServiceImpl implements OrderService {public void order() {System.out.println("修改数据库订单操作..");}}public class JdkInvocationHandler implements InvocationHandler {/*** 目标代理对象*/public Object target;public JdkInvocationHandler(Object target) {this.target = target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(">>>日志收集开始>>>>");// 执行代理对象方法Object reuslt = method.invoke(target, args);System.out.println(">>>日志收集结束>>>>");return reuslt;}/*** 获取代理对象接口** @param <T>* @return*/public <T> T getProxy() {return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);}}//测试JdkInvocationHandler jdkInvocationHandler = new JdkInvocationHandler(new OrderServiceImpl());OrderService proxy = jdkInvocationHandler.getProxy();proxy.order();
原理分析:
1、获取代理的生成的class文件
System.getProperties().put(“sun.misc.ProxyGenerator.saveGeneratedFiles”,
“true”);
2、使用反编译工具进行反编译
CGLIB动态代理
JDK动态代理是通过实现接口来实现 的,而CGLIB是通过继承实现类来实现的;其底层是通过ASM字节码框架来动态修改目标类的字节码来实现的,从而CGLI代理类对象实现动态代理效率比Jdk动态代理反射技术效率要高。
缺点:对于被代理类中的final方法,无法进行代理,因为子类中无法重写final函数
实现步骤:
实现MethodInterceptor接口的intercept方法后,所有生成的代理方法都调用这个方法。
intercept方法的具体参数有
obj 目标类的实例
1、 method
目标方法实例(通过反射获取的目标方法实例)
2、 args
目标方法的参数
3.、proxy
代理类的实例
该方法的返回值就是目标方法的返回值。
public class OrderServiceImpl {public void order() {System.out.println("用户下单操作..");}}public class CglibMethodInterceptor implements MethodInterceptor {public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("<<<<<日志收集开始...>>>>>>>");Object reuslt = proxy.invokeSuper(obj, args);System.out.println("<<<<<日志收集结束...>>>>>>>");return reuslt;}}System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");CglibMethodInterceptor cglibMethodInterceptor = new CglibMethodInterceptor();Enhancer enhancer = new Enhancer();// 设置代理类的付类enhancer.setSuperclass(OrderServiceImpl.class);// 设置回调对象enhancer.setCallback(cglibMethodInterceptor);// 创建代理对象OrderServiceImpl orderServiceImpl = (OrderServiceImpl) enhancer.create();orderServiceImpl.order();
maven依赖
<dependencies><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.2.12</version></dependency></dependencies>
8、深入理解
自己手写
思路:
1.拼接代理类的源代码
2. 写入到到本地文件中.
3. 使用JavaCompiler技术将源代码编译成class文件
4.使用classLoader 加载到内存中.
5.指明初始化有参数构造函数
public interface OrderService {public void order() throws Throwable;}public class OrderServiceImpl implements OrderService {public void order() {System.out.println("数据库订单执行操作");}}public interface MyExtJdkInvocationHandler {/*** @param proxy 代理类* @param method 目标方法* @param args 参数* @return* @throws Throwable*/public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;}public class MyJdkInvocationHandler implements MyExtJdkInvocationHandler {/*** 目标对象 被代理的类 真实访问的类的对象*/private Object target;public MyJdkInvocationHandler(Object target) {this.target = target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("<<<<<<<<<纯手写jdk动态代理日志开始>>>>>>>>>>");Object result = method.invoke(target, args);// 使用java的反射执行System.out.println("<<<<<<<<纯手写jdk动态代理结束>>>>>>>>>>");return result;}}public class MyProxy {static String rt = "\r\t";public static Object newProxyInstance(JavaClassLoader javaClassLoader,Class<?> classInfo,MyExtJdkInvocationHandler h) {//1.拼接代理类的源代码try {// 1.创建代理类java源码文件,写入到硬盘中..Method[] methods = classInfo.getMethods();String proxyClass = "package com.mayikt.ext.proxy;" + rt+ "import java.lang.reflect.Method;" + rt+ "import com.mayikt.ext.proxy.MyExtJdkInvocationHandler;" + rt+ "public class $Proxy0 implements " + classInfo.getName() + "{" + rt+ "MyExtJdkInvocationHandler h;" + rt+ "public $Proxy0(MyExtJdkInvocationHandler h)" + "{" + rt+ "this.h= h;" + rt + "}"+ getMethodString(methods, classInfo) + rt + "}";// 2. 写入到到本地文件中..String filename = "d:/$Proxy0.java";File f = new File(filename);FileWriter fw = new FileWriter(f);fw.write(proxyClass);fw.flush();fw.close();// 3. 将源代码编译成class文件JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);Iterable units = fileMgr.getJavaFileObjects(filename);JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);t.call();fileMgr.close();// 4.使用classLoader 加载到内存中..Class<?> $Proxy0 = javaClassLoader.findClass("$Proxy0");// 5.指明初始化有参数构造函数Constructor<?> constructor = $Proxy0.getConstructor(MyExtJdkInvocationHandler.class);Object o = constructor.newInstance(h);return o;} catch (Exception e) {e.printStackTrace();}return null;}public static String getMethodString(Method[] methods, Class intf) {String proxyMe = "";for (Method method : methods) {proxyMe += "public void " + method.getName() + "() throws Throwable {" + rt+ "Method md= " + intf.getName() + ".class.getMethod(\"" + method.getName()+ "\",new Class[]{});" + rt+ "this.h.invoke(this,md,null);" + rt + "}" + rt;}return proxyMe;}public static void main(String[] args) {newProxyInstance(null, OrderService.class, null);}}
工具类
public class JavaClassLoader extends ClassLoader {private File classPathFile;public JavaClassLoader(){// String classPath=JavaClassLoader.class.getResource("").getPath();String classPath="D:\\";this.classPathFile=new File(classPath);}@Overridepublic Class<?> findClass(String name) throws ClassNotFoundException {String className= JavaClassLoader.class.getPackage().getName()+"."+name;if(classPathFile!=null){File classFile=new File(classPathFile,name.replaceAll("\\.","/")+".class");if(classFile.exists()){FileInputStream in=null;ByteArrayOutputStream out=null;try {in=new FileInputStream(classFile);out=new ByteArrayOutputStream();byte[] buff=new byte[1024];int len;while ((len=in.read(buff))!=-1){out.write(buff,0,len);}return defineClass(className,out.toByteArray(),0,out.size());}catch (Exception e){e.printStackTrace();}finally {if(in!=null){try {in.close();} catch (IOException e) {e.printStackTrace();}}if(out!=null){try {out.close();} catch (IOException e) {e.printStackTrace();}}}}}return null;}}
java反射
public static void main(String[] args) {MemberServiceImpl memberService = new MemberServiceImpl();Class member= memberService.getClass();Annotation[] annotations=member.getAnnotations();for(int i=0;i<annotations.length;i++){//org.springframework.web.bind.annotation.RestControllerSystem.out.println(annotations[i].annotationType().getName());//RestControllerSystem.out.println(annotations[i].annotationType().getSimpleName());}}@RestControllerpublic class MemberServiceImpl {}
