首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

动态署理的演示

2012-08-29 
动态代理的演示使用动态字节码生成技术实现AOP原理是在运行期间目标字节码加载后,生成目标类的子类,将切面

动态代理的演示
使用动态字节码生成技术实现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 {@Overridepublic void show_Business2() {System.out.println("show_Business2");}@Overridepublic 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;}@Overridepublic 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 {@Overridepublic Object intercept(Object target, Method method, Object[] args,MethodProxy proxy) throws Throwable {// 执行原有逻辑,注意这里是invokeSuperObject 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将其分离,并动态挂接业务。
权限验证,方法执行前验证是否有权限执行当前方法,没有则抛出没有权限执行异常,由业务代码捕捉。

热点排行