`

动态代理的演示

 
阅读更多
使用动态字节码生成技术实现AOP原理是在运行期间目标字节码加载后,生成目标类的子类,将切面逻辑加入到子类中,所以使用Cglib实现AOP不需要基于接口

定义两个接口
package AOP;

public interface Business1 {
	public void show_Business1();
}





package AOP;

public interface Business2 {
	public void show_Business2();
}


定义实现类:
package AOP;

public class Business implements Business1, Business2 {

	@Override
	public void show_Business2() {
		System.out.println("show_Business2");

	}

	@Override
	public void show_Business1() {
		System.out.println("show_Business1");

	}

}


定义日志拦截:
package AOP;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class LogInvocationHandler implements InvocationHandler {

	private Object target; // 目标对象

	LogInvocationHandler(Object target) {
		this.target = target;
	}



	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		// 执行原有逻辑
		Object rev = method.invoke(target, args);
			System.out.println(method.getName()+":");
		return rev;
	}

}





定义动态实现类
package AOP;


import java.lang.reflect.Proxy;

public class DynamicProxyDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Class[] proxyInterface = new Class[] { Business1.class, Business2.class };
		ClassLoader classLoader = DynamicProxyDemo.class.getClassLoader();
		LogInvocationHandler logInvocationHandler = new LogInvocationHandler(
				new Business());
		Business1 business1=(Business1)Proxy.newProxyInstance(classLoader, proxyInterface,
				logInvocationHandler);
		business1.show_Business1();
		((Business2)business1).show_Business2();

	}

}




CglibTest
package Cglib;

import net.sf.cglib.proxy.Enhancer;

public class CglibTest {
	public static void main(String[] args) {
		byteCodeGe();
	}

	public static void byteCodeGe() {
		// 创建一个织入器
		Enhancer enhancer = new Enhancer();
		// 设置父类
		enhancer.setSuperclass(Business.class);
		// 设置需要织入的逻辑
		enhancer.setCallback(new LogIntercept());
		// 使用织入器创建子类
		Business newBusiness = (Business) enhancer.create();
		newBusiness.show_Business1();
		newBusiness.show_Business2();
	}

}


Intercept
package Cglib;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 * 记录日志
 */
public class LogIntercept implements MethodInterceptor {

	@Override
	public Object intercept(Object target, Method method, Object[] args,
			MethodProxy proxy) throws Throwable {
		// 执行原有逻辑,注意这里是invokeSuper
		Object rev = proxy.invokeSuper(target, args);
		// 执行织入的日志
			System.out.println("记录日志");
		return rev;
	}

}


业务逻辑
package Cglib;

public class Business {

	public void show_Business2() {
		System.out.println("show_Business2");

	}

	public void show_Business1() {
		System.out.println("show_Business1");

	}

}



3.3 自定义类加载器
如果我们实现了一个自定义类加载器,在类加载到JVM之前直接修改某些类的方法,并将切入逻辑织入到这个方法里,然后将修改后的字节码文件交给虚拟机运行,那岂不是更直接。

Javassist是一个编辑字节码的框架,可以让你很简单地操作字节码。它可以在运行期定义或修改Class。使用Javassist实现AOP的原理是在字节码加载前直接修改需要切入的方法。这比使用Cglib实现AOP更加高效,并且没太多限制,实现原理如下图:
	public static void main(String[] args) throws Throwable {
		//获取存放CtClass的容器ClassPool 
		ClassPool cp = ClassPool.getDefault(); 
		CtClass cc = cp.get(className);
//		CtMethod targetM = null;
		CtMethod targetM = cc.getDeclaredMethod("doSomeThing");
		targetM.insertBefore("{ System.out.println(\"记录日志前\"); }");
		targetM.insertAfter("{ System.out.println(\"记录日志后\"); }");
		Class c = cc.toClass();
		Business b = (Business) c.newInstance();
		b.doSomeThing2();
		b.doSomeThing();
	}


Business
public class Business { 

    public boolean doSomeThing() { 
        System.out.println("doSomeThing"); 
        return true; 
    } 

    public void doSomeThing2() { 
        System.out.println("doSomeThing2"); 
    } 

} 


3.4 字节码转换
    自定义的类加载器实现AOP只能拦截自己加载的字节码,那么有没有一种方式能够监控所有类加载器加载字节码呢?有,使用Instrumentation,它是 Java 5 提供的新特性,使用 Instrumentation,开发者可以构建一个字节码转换器,在字节码加载前进行转换。本节使用Instrumentation和javassist来实现AOP。

3.4.1 构建字节码转换器
    首先需要创建字节码转换器,该转换器负责拦截Business类,并在Business类的doSomeThing方法前使用javassist加入记录日志的代码。



4 AOP实战
说了这么多理论,那AOP到底能做什么呢? AOP能做的事情非常多。
性能监控,在方法调用前后记录调用时间,方法执行太长或超时报警。
缓存代理,缓存某方法的返回值,下次执行该方法时,直接从缓存里获取。
软件破解,使用AOP修改软件的验证类的判断逻辑。
记录日志,在方法执行前后记录系统日志。
工作流系统,工作流系统需要将业务代码和流程引擎代码混合在一起执行,那么我们可以使用AOP将其分离,并动态挂接业务。
权限验证,方法执行前验证是否有权限执行当前方法,没有则抛出没有权限执行异常,由业务代码捕捉。
分享到:
评论

相关推荐

    java jdk 动态代理 演示demo

    Java JDK 动态代理是一种强大的特性,它允许我们在运行时创建代理对象,这些代理对象可以扩展或增强已存在的接口实现。动态代理在处理AOP(面向切面编程)场景、事件监听、性能监控等方面有着广泛的应用。下面我们将...

    java jdk 动态代理演示demo2

    在“java jdk 动态代理演示demo2”中,可能还包括将生成的字节码保存到本地的步骤。Java的动态代理类在内存中生成,通常不需要手动处理字节码。但如果需要,可以使用`javassist`库或其他工具将字节码写入文件。这...

    使用动态代理演示Spring的AOP编程原理

    为了说明Spring的AOP原理,本人使用代理模式中的动态代理完成演示AOP编程的原理的演示。相信,如果你耐心看完整个程序(几乎一行注释一行代码),那么你对Spring这个东西就不是觉得有什么神秘了! 阅读对象:凡是喜爱...

    java jdk 动态代理演示demo

    Java JDK 动态代理是一种强大的特性,它允许我们在运行时创建代理对象,这些代理对象能够拦截方法调用并在调用前后执行自定义的行为。在Java中,动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect....

    使用cglib演示动态代理时用到的jar包 aop 动态代理

    1. 引入CGLIB库:在项目中引入CGLIB的jar包,如题目中的"使用cglib演示动态代理时用到的jar包"。 2. 创建Enhancer对象:这是CGLIB的核心类,用于配置代理对象的生成。 3. 设置回调机制:通过setCallback()方法,...

    Java动态代理案例演示代码

    Java动态代理是Java语言提供的一种强大的机制,它允许在运行时创建具有特定接口的代理类对象,这些代理类对象能够对方法调用进行拦截和增强。动态代理在很多场景下非常有用,例如AOP(面向切面编程)、事件监听、...

    JDK动态代理_JDK动态代理

    下面是一个简单的示例,演示了如何使用JDK动态代理为一个接口创建代理对象,并在方法调用前后添加日志记录功能。 ```java /** * 业务接口 */ public interface IHello { void hello(String name); } /** * ...

    动态代理例子

    在提供的`ProxyTest`文件中,可能包含了这样的示例代码,演示了如何创建和使用动态代理。你可以通过查看和运行这段代码来加深对动态代理的理解。 总结来说,动态代理是Java中一种强大的设计模式,它允许我们为现有...

    DynamicProxy:一个简单实用的JDK动态代理演示

    本文将深入探讨JDK动态代理,并通过一个简单的实例来演示其用法。 动态代理主要由两个核心类组成:`java.lang.reflect.Proxy` 和 `java.lang.reflect.InvocationHandler`。`Proxy` 类是用于创建动态代理对象的工厂...

    Java动态代理和Java反射的Demo演示

    Java动态代理和反射是Java编程中的重要特性,它们在实现高度灵活和动态的代码执行方面发挥着关键作用。本文将通过实例演示这两种技术,并详细解释它们的工作原理。 首先,我们来了解一下Java动态代理。动态代理主要...

    JAVA JDK静态代理、动态代理、CGlib代理的代码演示

    Java提供了两种主要的代理实现方式:JDK静态代理和动态代理,另外还有第三方库如CGlib提供的代理实现。下面我们将详细探讨这些代理技术,并通过代码演示来理解它们的工作原理。 ### 1. JDK静态代理 静态代理是我们...

    springboot中的 动态代理的选择测试代码

    在压缩包文件`springbootaop`中,很可能包含了上述的配置和切面类代码,用于演示Spring Boot中动态代理的使用。通过分析这些代码,我们可以更深入地理解如何在实际项目中运用动态代理实现AOP功能。 总结一下,...

    qt qtableview动态代理

    在提供的压缩包文件"myTable"中,可能包含了一个示例项目,演示如何实现上述动态代理功能。通过解压并运行这个项目,你可以看到如何将QTableView的单元格转化为可编辑的控件。 8. **实际应用** 动态代理在数据...

    java动态代理demo

    本示例将带你深入理解Java动态代理的概念,并通过一个简单易懂的demo来演示其用法。 1. **Java动态代理概念** Java动态代理基于Java反射机制,可以在运行时动态地创建代理类和代理对象。与静态代理(即手动编写...

    动态代理和静态代理demo

    代理模式通常分为静态代理和动态代理两种实现方式,这里我们将详细探讨这两种代理模式,并通过一个简单的Java示例进行演示。 ### 静态代理 静态代理是最基础的代理形式,它的实现主要依靠继承或接口实现。在静态...

    动态代理由浅入深

    在本文中,我们通过一个简单的例子来演示动态代理的实现。我们定义了一个接口 Milk,有两个方法:sell 和 make。然后,我们定义了一个品牌商 YiDianDian,它实现了 Milk 接口。接着,我们使用动态代理生成 ...

    AOP 动态代理demo

    在"AopDemo"这个文件中,我们可以期待看到一个完整的示例,它将演示如何使用JDK动态代理和CGLIB来创建代理对象,并添加增强功能。通过这个例子,开发者可以更好地理解AOP的工作原理,以及如何在实际项目中应用这两种...

    spring 的动态代理详解

    #### 动态代理实例演示 下面通过一个简单的示例来展示动态代理的创建过程: ```java public class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler...

    Java中动态代理的介绍及实例

    #### 四、动态代理实例演示 示例代码展示了如何使用JDK动态代理创建一个代理对象,并通过该代理对象调用目标对象的方法。关键步骤如下: 1. 定义一个`DynamicProxy`类实现`InvocationHandler`接口,内部存储目标...

    Spring学习笔记(13)----动态代理模式分析演示

    在本篇Spring学习笔记中,我们将深入探讨动态代理模式,并结合Spring框架的实现进行分析演示。动态代理模式是Java编程中一种重要的设计模式,它允许我们在不修改原对象代码的情况下,为对象添加额外的功能或行为。...

Global site tag (gtag.js) - Google Analytics