`

实现动态代理

 
阅读更多

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呢?

 请参考

 参考文章  

 

0
0
分享到:
评论

相关推荐

    Nginx+lua通过url传参的方式实现动态代理

    ### Nginx+Lua通过URL传参方式实现动态代理 #### 概述 在现代Web应用开发中,灵活地管理后端服务之间的通信是至关重要的。动态代理技术为这一需求提供了解决方案,使得前端可以方便地根据业务逻辑将请求转发至不同...

    Java实现动态代理

    CGLIB通过创建目标类的子类来实现动态代理,所以不需要目标类实现接口。 首先,需要引入CGLIB库,然后使用`net.sf.cglib.proxy.Enhancer`类来创建代理对象。Enhancer提供了丰富的API来定制代理对象的行为,比如...

    CGlib实现动态代理(承接上面JDK实现动态代理)

    以下是使用CGlib实现动态代理的关键步骤: 1. 引入依赖:在项目中,需要引入CGlib的相关库,通常是在Maven或Gradle的配置文件中添加对应的依赖。 2. 创建Enhancer对象:Enhancer是CGlib的核心类,它提供了创建代理...

    jdk和cglib实现动态代理

    分别使用jdk和cglib实现动态代理,包含UML图。还有相关的博客链接:http://blog.csdn.net/y_love_f/article/details/46345581.博客中有具体的代理解释

    Java动态代理两种实现方式

    Cglib是基于ASM库来实现的,可以为非final类生成子类并覆盖方法,从而实现动态代理。 #### 1. 引入Cglib库 在项目中引入Cglib库,如使用Maven,可以在pom.xml中添加依赖: ```xml <groupId>cglib <artifactId>...

    Mybatis实现动态代理,动态SQL

    "Mybatis实现动态代理,动态SQL" Mybatis框架可以通过配置的形式为DAO接口生成动态代理实现类,从而简化程序开发,提高开发效率。在实现动态代理时,需要满足以下条件:接口全命名必须和SQL映射文件中的namespace...

    Emit实现动态代理

    C#的Emit实现动态代理的过程大致如下: 1. **定义委托**:首先,我们需要定义一个委托类型,这个委托类型代表我们要代理的方法。例如,如果有一个名为`Execute`的方法,我们可以定义一个`Action`或者`Func`类型的...

    工厂类中实现动态代理

    总结起来,"工厂类中实现动态代理"是将工厂模式、动态代理和Spring的AOP思想结合起来,以达到在运行时动态地为对象添加额外功能的目的。通过这种方式,我们可以更好地组织代码,提高代码的可读性和可维护性,同时...

    javassit实现动态代理解决代理必须要接口的缺憾

    在Java中,我们通常使用接口来实现动态代理,比如JDK的java.lang.reflect.Proxy类,但是这种方式要求目标对象必须实现至少一个接口。然而,Javaassist提供了一种方式,即使没有接口,也能创建动态代理,弥补了这个...

    cglib实现动态代理依赖jar包

    这个“cglib实现动态代理依赖jar包”包含了两个核心的JAR文件:asm-5.1.jar和cglib-3.2.4.jar。 **ASM库**: ASM是一个字节码操控和分析框架,它可以直接生成和修改Java类和Android Dalvik字节码。ASM库主要用在...

    java常用设计模式及JDK与CGLIB实现动态代理区别(源码)

    java常用设计模式及JDK与CGLIB实现动态代理区别(源码) /** * 使用cglib动态代理 * @author * */ public class BookFacadeProxy implements MethodInterceptor{ private Object target; @Override public...

    java-jdk动态代理的实现demo

    在Java中,JDK提供了一个`java.lang.reflect.Proxy`类和一个`java.lang.reflect.InvocationHandler`接口,它们是实现动态代理的关键。Proxy类用于创建代理对象,而InvocationHandler接口定义了处理方法调用的逻辑。 ...

    静态代理动态代理测试,模拟jdk实现动态代理

    在实际应用中,动态代理常用于AOP(面向切面编程)场景,例如Spring框架中的AOP代理就是基于JDK动态代理或者CGLIB来实现的,可以在方法调用前、后或异常时插入自定义的行为。 通过上述的静态代理和动态代理的讲解,...

    JAVA实现动态代理的简单流程

    在深入探讨Java动态代理的实现过程之前,我们首先需要理解动态代理的基本概念及其在Java中的应用价值。动态代理,顾名思义,是在运行时动态创建代理对象的一种机制,它无需在编译期就确定代理类的具体实现,而是通过...

    反射实现 AOP 动态代理模式(Spring AOP 的实现原理)

    在Java开发中,反射机制是实现动态代理的关键技术之一。反射提供了在运行时访问和操作类的能力,这使得动态代理的实现成为可能。在Java中,可以使用java.lang.reflect包下的相关类和接口实现动态代理。 例如,通过...

    ioc框架,通过动态代理实现.

    1. JDK动态代理:JDK内置的java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口提供了实现动态代理的能力。当被代理的类实现了至少一个接口时,我们可以使用JDK动态代理来创建一个代理类,这个代理...

    Java动态代理详解; CGLib实现动态代理1

    Java 动态代理详解与 CGLib 实现 在 Java 中,代理模式是一种设计模式,它允许我们在不修改原有对象的基础上,为对象增加额外的功能。代理模式的核心在于代理类(Proxy)作为真实对象(RealSubject)的替代品,提供...

    jdk与cglib动态代理与底层实现

    JDK和CGLIB是Java中实现动态代理的两种主要方式,它们在Spring框架中扮演着关键角色,尤其是在AOP(面向切面编程)中。 1. **JDK动态代理**: JDK动态代理基于Java的接口机制实现,因此,要使用JDK动态代理,被...

    三种动态代理的实现

    CGLIB是通过继承目标类来实现动态代理的,因此当目标类不可被继承时(如final修饰),JDK动态代理就无法使用,这时可以考虑使用CGLIB。 CGLIB的使用需要引入相关依赖,并通过`org.springframework.cglib.proxy....

Global site tag (gtag.js) - Google Analytics