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呢?
请参考
相关推荐
### Nginx+Lua通过URL传参方式实现动态代理 #### 概述 在现代Web应用开发中,灵活地管理后端服务之间的通信是至关重要的。动态代理技术为这一需求提供了解决方案,使得前端可以方便地根据业务逻辑将请求转发至不同...
CGLIB通过创建目标类的子类来实现动态代理,所以不需要目标类实现接口。 首先,需要引入CGLIB库,然后使用`net.sf.cglib.proxy.Enhancer`类来创建代理对象。Enhancer提供了丰富的API来定制代理对象的行为,比如...
以下是使用CGlib实现动态代理的关键步骤: 1. 引入依赖:在项目中,需要引入CGlib的相关库,通常是在Maven或Gradle的配置文件中添加对应的依赖。 2. 创建Enhancer对象:Enhancer是CGlib的核心类,它提供了创建代理...
分别使用jdk和cglib实现动态代理,包含UML图。还有相关的博客链接:http://blog.csdn.net/y_love_f/article/details/46345581.博客中有具体的代理解释
Cglib是基于ASM库来实现的,可以为非final类生成子类并覆盖方法,从而实现动态代理。 #### 1. 引入Cglib库 在项目中引入Cglib库,如使用Maven,可以在pom.xml中添加依赖: ```xml <groupId>cglib <artifactId>...
"Mybatis实现动态代理,动态SQL" Mybatis框架可以通过配置的形式为DAO接口生成动态代理实现类,从而简化程序开发,提高开发效率。在实现动态代理时,需要满足以下条件:接口全命名必须和SQL映射文件中的namespace...
C#的Emit实现动态代理的过程大致如下: 1. **定义委托**:首先,我们需要定义一个委托类型,这个委托类型代表我们要代理的方法。例如,如果有一个名为`Execute`的方法,我们可以定义一个`Action`或者`Func`类型的...
总结起来,"工厂类中实现动态代理"是将工厂模式、动态代理和Spring的AOP思想结合起来,以达到在运行时动态地为对象添加额外功能的目的。通过这种方式,我们可以更好地组织代码,提高代码的可读性和可维护性,同时...
在Java中,我们通常使用接口来实现动态代理,比如JDK的java.lang.reflect.Proxy类,但是这种方式要求目标对象必须实现至少一个接口。然而,Javaassist提供了一种方式,即使没有接口,也能创建动态代理,弥补了这个...
这个“cglib实现动态代理依赖jar包”包含了两个核心的JAR文件:asm-5.1.jar和cglib-3.2.4.jar。 **ASM库**: ASM是一个字节码操控和分析框架,它可以直接生成和修改Java类和Android Dalvik字节码。ASM库主要用在...
java常用设计模式及JDK与CGLIB实现动态代理区别(源码) /** * 使用cglib动态代理 * @author * */ public class BookFacadeProxy implements MethodInterceptor{ private Object target; @Override public...
在Java中,JDK提供了一个`java.lang.reflect.Proxy`类和一个`java.lang.reflect.InvocationHandler`接口,它们是实现动态代理的关键。Proxy类用于创建代理对象,而InvocationHandler接口定义了处理方法调用的逻辑。 ...
在实际应用中,动态代理常用于AOP(面向切面编程)场景,例如Spring框架中的AOP代理就是基于JDK动态代理或者CGLIB来实现的,可以在方法调用前、后或异常时插入自定义的行为。 通过上述的静态代理和动态代理的讲解,...
在深入探讨Java动态代理的实现过程之前,我们首先需要理解动态代理的基本概念及其在Java中的应用价值。动态代理,顾名思义,是在运行时动态创建代理对象的一种机制,它无需在编译期就确定代理类的具体实现,而是通过...
在Java开发中,反射机制是实现动态代理的关键技术之一。反射提供了在运行时访问和操作类的能力,这使得动态代理的实现成为可能。在Java中,可以使用java.lang.reflect包下的相关类和接口实现动态代理。 例如,通过...
1. JDK动态代理:JDK内置的java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口提供了实现动态代理的能力。当被代理的类实现了至少一个接口时,我们可以使用JDK动态代理来创建一个代理类,这个代理...
Java 动态代理详解与 CGLib 实现 在 Java 中,代理模式是一种设计模式,它允许我们在不修改原有对象的基础上,为对象增加额外的功能。代理模式的核心在于代理类(Proxy)作为真实对象(RealSubject)的替代品,提供...
JDK和CGLIB是Java中实现动态代理的两种主要方式,它们在Spring框架中扮演着关键角色,尤其是在AOP(面向切面编程)中。 1. **JDK动态代理**: JDK动态代理基于Java的接口机制实现,因此,要使用JDK动态代理,被...
CGLIB是通过继承目标类来实现动态代理的,因此当目标类不可被继承时(如final修饰),JDK动态代理就无法使用,这时可以考虑使用CGLIB。 CGLIB的使用需要引入相关依赖,并通过`org.springframework.cglib.proxy....