AOP的实现有两种,一种是接口的实现,一种是产生自己实现,分别的代表为JDK的Proxy和CGLIB的Proxy
下面是模拟接口代理实现 ,通过模拟JDK的动态代理,更深刻的理解
通过动态代理可以面向切面编程
1 定义被代理的对象和接口
public interface BookInterface { void selling(); }
public interface PhoneInterface { void selling(); }
public class Book implements BookInterface { @Override public void selling() { System.out.println("books selling....."); } }
public class VivoPhone implements PhoneInterface { @Override public void selling() { System.out.println("selling vivo x5"); } }
2 定义切面类
public class TimeAspect { static long bgn; public static void before(){ bgn = System.currentTimeMillis(); System.out.println("begin time... " + bgn); } public static void after(){ long end = System.currentTimeMillis(); System.out.println("end time... " + (end-bgn)); } }
public class LogAspect{ public static void before(){ System.out.println("begin log..."); } public static void after(){ System.out.println("finish log..."); } }
3 定义InvocationHander 代理接口
import java.lang.reflect.Method; public interface InvocationHander { public void invoke(Object o,Method m); }
代理类(切面编程里面也可以做一些特殊的处理)
import java.lang.reflect.Method; public class ProxyHander implements InvocationHander { private Object target; public ProxyHander(Object target) { this.target = target; } @Override public void invoke(Object o, Method m) { try { TimeAspect.before(); if(!(o instanceof BookInterface)){//只有非BookInterface接口调用日志 LogAspect.before(); } m.invoke(target); if(!(o instanceof BookInterface)){ LogAspect.after(); } TimeAspect.after(); } catch (Exception e) { e.printStackTrace(); } } }
动态代理类
import java.io.File; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import javax.tools.JavaCompiler; import javax.tools.JavaCompiler.CompilationTask; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; import org.apache.commons.io.FileUtils; public class Proxy { /* * 空的构造函数 */ private Proxy(){ } /* * 返回代理类 */ public static Object newProxyInstance(Class inter,InvocationHander h){ String packageName = inter.getPackage().getName(); // String temp = new String(packageName); String proxyClassName = "$"+packageName.replace(".","_") + "_" + inter.getSimpleName() +"Proxy"; String InHanderPackage = h.getClass().getPackage().getName(); String rt = "\r\n";// 换行 String methodCode = ""; for (Method method:inter.getMethods()) { methodCode+=" @Override"+rt+ " public void "+ method.getName()+"() {"+rt+ " try{"+rt+ " Method method = "+inter.getName()+".class.getMethod(\"" + method.getName()+ "\");"+rt+ " h.invoke(this,method); "+rt+ " }catch(Exception e ){" +rt+ " e.printStackTrace();" +rt+ " }"+rt+ " }"; } /* * 总的java代码 */ String javaCode= "package "+packageName+";"+rt+ "import "+InHanderPackage+".InvocationHander;"+rt+ "import java.lang.reflect.Method;"+rt+ "public class "+proxyClassName+" implements "+inter.getName()+" {"+rt+ " public "+proxyClassName+"("+InHanderPackage+".InvocationHander h) {"+rt+ " super();"+rt+ " this.h = h;"+rt+ " }"+rt+ " private "+InHanderPackage+".InvocationHander h;"+rt+ methodCode+rt+ "}"; /* * 生成java文件 */ // 生成文件路径 String filename = System.getProperty("user.dir")+"/bin/"+packageName.replace(".", "//")+"/"+proxyClassName+".java"; File file = new File(filename); try { // 需要commons-io的jar方便的操作文件 FileUtils.writeStringToFile(file, javaCode); } catch (IOException e) { e.printStackTrace(); } // 编译 拿到编译器 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); // 文件管理 StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null); //获取文件 Iterable units = fileMgr.getJavaFileObjects(filename); // 编译任务 CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units); // call进行编译 t.call(); try { fileMgr.close(); } catch (IOException e) { e.printStackTrace(); } // load到内存 ClassLoader cl = ClassLoader.getSystemClassLoader(); try { Class c = cl.loadClass(packageName+"."+proxyClassName); Constructor ctr = c.getConstructor(InvocationHander.class); return ctr.newInstance(h); } catch (Exception e) { e.printStackTrace(); } return null; } }
4 测试
import org.junit.After; import org.junit.Before; import org.junit.Test; public class TestProxy { @Before public void before(){ System.out.println("-----------------start-------------------"); } @Test public void test() { Book book = new Book(); InvocationHander h = new ProxyHander(book); BookInterface bi = (BookInterface)Proxy.newProxyInstance(BookInterface.class,h); bi.selling(); // 没有日志打印 System.out.println("==================分割=============================="); PhoneInterface car = new VivoPhone(); h = new ProxyHander(car); PhoneInterface pi = (PhoneInterface)Proxy.newProxyInstance(PhoneInterface.class,h); pi.selling(); // 有日志打印 } @After public void after(){ System.out.println("-----------------end-------------------"); } }
Proxy类里面生成代理类名称的方法是根据包名来的,全类名长度加起来超过250多个长度可能会让java类无法编译,那就需要特殊处理了。超过250个长度的全类名那种项目没见过,不考虑
上面是他的原理,spring中如何使用aop呢?
请参考
相关推荐
分别使用jdk和cglib实现动态代理,包含UML图。还有相关的博客链接:http://blog.csdn.net/y_love_f/article/details/46345581.博客中有具体的代理解释
需求大致如下:通过url传参的方式,让Nginx代理到不同的服务器 浏览器输入:http://127.0.0.1/remote?port=8081被代理到:http://192.168.108.2:8081
Java实现动态代理的两种方式。 相对来说cglib更加方便。可以实现为实现接口的类(非final类)
Emit实现动态代理 参照java的动态代理的使用感觉实现C#版
这个是个人做的JAVA实现动态代理的笔记
java常用设计模式及JDK与CGLIB实现动态代理区别(源码) /** * 使用cglib动态代理 * @author * */ public class BookFacadeProxy implements MethodInterceptor{ private Object target; @Override public...
详见:https://blog.csdn.net/qq_37651267/article/details/90083914
本工程是对静态代理,动态代理的测试,并且实现了对jdk动态代理的简单模拟!
NULL 博文链接:https://gz383.iteye.com/blog/591079
cglib实现动态代理依赖jar包,包括asm-5.1.jar和cglib-3.2.4.jar
Mybatis+JDBC实现的动态代理,动态SQL,步骤较为详细:1)接口绑定方案;2)实现查询:方法参数为多个基本类型;3)动态SQL;4)缓存
AOP动态代理描述了Spring AOP中使用Java高级技术功能实现的动态代理,为Spring IOC等高级开发实现了逻辑功能;
利用工厂开发模式结合动态代理 很好的结合了spring的切面编程思想 将业务逻辑层更数据访问层结合 实现统一控制
主要介绍了Spring如何基于Proxy及cglib实现动态代理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
简介Java编程的目标是实现现实不能完成的,优化现实能够完成的,是一种虚拟技术。生活中的方方面面都可以虚拟到代码中。代理模式所讲的就是现实生活中的这么一个概念:
测试springboot使用动态代理时候的一些代码,具体参考博客http://blog.csdn.net/maoyeqiu/article/details/76546468
代理模式及手实现动态代理(aop原理)一、代理模式1. 定义2. 示例(1)静态代理(2)动态代理3. 通用类图4. 代理模式的优点二、jdk动态代理实现原理1. jdk动态代理源码分析(通过该示例学会阅读源码的方法)2.jdk动态...
实现动态代理的两种方式: 第一种是JDK提供的基于接口的动态代理,要求被代理的类必须至少实现一个接口。 2. 第二种是第三方cglib提供的基于子类的动态代理,。至少要继承一个类。 我们这里 来讲解,动态代理,以及...
实现了一份jdk动态代理的demo,做了详细注释,供以后复习使用,另外,这里为什么需要大于100个字节才能传资源?我就不想那么多不行吗???