java动态代理和cglib动态代理示例分享
java动态代理和cglib动态代理示例分享
发布时间:2016-12-28 来源:查字典编辑
摘要:java动态代理类可以分为两种。静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在...

java动态代理类可以分为两种。

静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。

动态代理:在程序运行时,运用反射机制动态创建而成。

一、首先我们进行java动态代理的演示。

现在我们有一个简单的业务接口Saying,如下:

复制代码 代码如下:

package testAOP;

public interface Saying {

public void sayHello(String name);

public void talking(String name);

}

一个简单的实现类SayingImpl,如下:

复制代码 代码如下:

package testAOP;

public class SayingImpl implements Saying {

@Override

public void sayHello(String name) {

// TODO Auto-generated method stub

System.out.println(name + ":大家好啊!");

}

@Override

public void talking(String name) {

// TODO Auto-generated method stub

System.out.println(name + ":我的意思是,我们要努力建设和谐社会!");

}

}

我们要实现的是,在sayHello和talking之前和之后分别动态植入处理。

JDK动态代理主要用到java.lang.reflect包中的两个类:Proxy和InvocationHandler.

InvocationHandler是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态的将横切逻辑和业务逻辑编织在一起。

Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。

如下,我们创建一个InvocationHandler实例:

复制代码 代码如下:

package testAOP;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {

private Object target;

MyInvocationHandler(Object target){

this.target = target;

}

@Override

public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {

//目标方法前执行

System.out.println("——————————————————————————");

System.out.println("下一位请登台发言!");

//目标方法调用

Object obj = method.invoke(target, args);

//目标方法后执行

System.out.println("大家掌声鼓励!");

return obj;

}

}

下面是测试:

复制代码 代码如下:

package testAOP;

import java.lang.reflect.Proxy;

public class JDKProxyTest {

public static void main(String[] args) {

// 希望被代理的目标业务类

Saying target = new SayingImpl();

// 将目标类和横切类编织在一起

MyInvocationHandler handler = new MyInvocationHandler(target);

// 创建代理实例

Saying proxy = (Saying) Proxy.newProxyInstance(

target.getClass().getClassLoader(),//目标类的类加载器

target.getClass().getInterfaces(),//目标类的接口

handler);//横切类

proxy.sayHello("小明");

proxy.talking("小丽");

}

}

运行情况如下:

复制代码 代码如下:

——————————————————————————

下一位请登台发言!

小明:大家好啊!

大家掌声鼓励!

——————————————————————————

下一位请登台发言!

小丽:我的意思是,我们要努力建设和谐社会!

大家掌声鼓励!

使用JDK动态代理有一个很大的限制,就是它要求目标类必须实现了对应方法的接口,它只能为接口创建代理实例。我们在上文测试类中的Proxy的newProxyInstance方法中可以看到,该方法第二个参数便是目标类的接口。如果该类没有实现接口,这就要靠cglib动态代理了。

CGLib采用非常底层的字节码技术,可以为一个类创建一个子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,并顺势植入横切逻辑。

二、接下来我们进行cglib动态代理的演示。

首先我们需要导包,我用的包是cglib-nodep-2.1_3.jar。

我们首先创建一个代理创建器CglibProxy:

复制代码 代码如下:

package testAOP.cglib;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;

import net.sf.cglib.proxy.MethodInterceptor;

import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor{

Enhancer enhancer = new Enhancer();

public Object getProxy(Class clazz) {

//设置需要创建的子类

enhancer.setSuperclass(clazz);

enhancer.setCallback(this);

//通过字节码技术动态创建子类实例

return enhancer.create();

}

@Override

public Object intercept(Object obj, Method method, Object[] args,

MethodProxy proxy) throws Throwable {

// TODO Auto-generated method stub

System.out.println("——————————————————————————");

System.out.println("下一位请登台发言!");

//目标方法调用

Object result = proxy.invokeSuper(obj, args);

//目标方法后执行

System.out.println("大家掌声鼓励!");

return result;

}

}

然后进行测试:

复制代码 代码如下:

package testAOP.cglib;

import testAOP.Saying;

import testAOP.SayingImpl;

public class CglibProxyTest {

public static void main(String[] args) {

CglibProxy proxy = new CglibProxy();

//通过动态生成子类的方式创建代理类

Saying target = (Saying) proxy.getProxy(SayingImpl.class);

target.sayHello("小明");

target.talking("小丽");

}

}

结果与JDK动态代理没有任何区别。

JDK动态代理和CGLib动态代理都是运行时增强,通过将横切代码植入代理类的方式增强。与此不同的是AspectJ,它能够在通过特殊的编译器在编译时期将横切代码植入增强,这样的增强处理在运行时候更有优势,因为JDK动态代理和CGLib动态代理每次运行都需要增强。

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新Java学习
热门Java学习
编程开发子分类