Java使用Proxy和CGLib实现动态代理

来源:互联网 发布:mysql设置主键从1开始 编辑:程序博客网 时间:2024/05/04 16:31

   在java中对一个方法进行改造有几种方法可以实现,分别是最常用的继承(extends)、动态代理和装饰者模式。继承是最简单也是用的最多的方法,但是还是有一些场景不适用,这个时候就可能会用到动态代理。使用动态代理可以通过两种方式实现:1、使用JDK自带的Proxy实现代理。2、使用第三方类库CGLib实现动态代理。

一、使用Proxy实现动态代理必须是需要代理的类实现了某一个接口,这样才能实现代理

下面介绍两种使用动态代理的方式实现的案例。

首先准备一个接口和两个实现类对这两个实现类分别进行改造

<span style="font-size:18px;">package com.ruijie.test;public interface Animal {public void eat();public void hello();}</span>
<span style="font-size:18px;">package com.ruijie.test;public class Cat implements Animal {public void eat() {System.out.println("猫在吃东西");}public void hello() {System.out.println("猫在汪汪的叫");}}</span>

<span style="font-size:18px;">package com.ruijie.test;public class Dog implements Animal {public void eat() {System.out.println("狗在吃东西");}public void hello() {System.out.println("狗在汪汪的叫");}}</span>



1、使用动态代理实现对一个方法进行改造

package com.ruijie.test;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class DynamicProxyDog {public static void main(String[] args) {final Dog dog = new Dog();// 利用动态代理的方式对Dog进行改造Animal proxy = (Animal) Proxy.newProxyInstance(Dog.class.getClassLoader(), Dog.class.getInterfaces(), new InvocationHandler(){public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {// 对eat方法进行改造if("eat".equalsIgnoreCase(method.getName())){System.out.println("这是一只动态代理的狗在吃。。。。");return null;}else {// 其余的方法原样返回return method.invoke(dog, args);}}});proxy.eat();proxy.hello();}}

最后得到的结果为:

2、使用动态代理的方法在被代理的之前和之后做一些处理(在处理事务的时候就很有用了!)

package com.ruijie.test;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class DynamicProxyCat {public static void main(String[] args) {final Cat cat = new Cat();// 利用动态代理的方式对Cat进行改造Animal proxy = (Animal) Proxy.newProxyInstance(Cat.class.getClassLoader(), Cat.class.getInterfaces(), new InvocationHandler(){public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {// 在方法运行之前做一些处理System.out.println("猫在吃之前。。。");Object object = method.invoke(cat, args);// 在方法运行之后做一些处理System.out.println("猫在吃之后。。。");return object;}});proxy.eat();proxy.hello();}}

最后的结果为:



二、使用CGlib实现动态代理

如果要对某一个类实现动态代理,但是该类并没有实现某个接口,那使用CGlib就非常合适。主要代码如下:

一个没有实现接口的类:

public class PersonServerImpl {private String user =null;public PersonServerImpl() {}public PersonServerImpl(String user) {this.user = user;}public String getUser() {return this.user;}@Overridepublic void save() {System.out.println("我是save方法");}@Overridepublic String getPersonName() {System.out.println("我是getPersonName方法");return "XX";}@Overridepublic void update() {System.out.println("我是update方法");}}
使用CGLib进行代理

public class CglibProxyFactory implements MethodInterceptor{private Logger logger = Logger.getLogger(this.getClass().getName());// 需要代理的对象private Object delegate;// 绑定对象,绑定的对象不是接口public Object createProxyInstance(Object delegate) {this.delegate = delegate;Enhancer enhancer = new Enhancer();enhancer.setSuperclass(this.delegate.getClass());enhancer.setCallback(this);return enhancer.create();}@Overridepublic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object result = null;PersonServerImpl server =  (PersonServerImpl) this.delegate;if (server.getUser() != null) {logger.debug("user不为空,通过!");result = methodProxy.invoke(delegate, args);}else {logger.debug("user为空,不通过!");}return result;}}
代理类搞定之后,进行测试:

@Testpublic void proxyTest2() {CglibProxyFactory proxy = new CglibProxyFactory();PersonServerImpl personServer = (PersonServerImpl) proxy.createProxyInstance(new PersonServerImpl("zhangsan"));personServer.save();}

通过测试之后也能实现与Proxy同样的功能。

0 0