Java使用Proxy和CGLib实现动态代理
在java中对一个方法进行改造有几种方法可以实现,分别是最常用的继承(extends)、动态代理和装饰者模式。继承是最简单也是用的最多的方法,但是还是有一些场景不适用,这个时候就可能会用到动态代理。使用动态代理可以通过两种方式实现:1、使用JDK自带的Proxy实现代理。2、使用第三方类库CGLib实现动态代理。
一、使用Proxy实现动态代理必须是需要代理的类实现了某一个接口,这样才能实现代理
下面介绍两种使用动态代理的方式实现的案例。
首先准备一个接口和两个实现类对这两个实现类分别进行改造
package com.zjp.dao;/*** 定义一个接口* @author zhujunpeng**/
public interface UserDao {public void addUser();
}
package com.zjp.dao.impl;import com.zjp.dao.UserDao;public class UserDaoImpl implements UserDao{@Overridepublic void addUser() {System.out.println("添加用户逻辑。。。。");}}
定义一个切点
package com.zjp.aspect;/*** 自定义切点* @author zhujunpeng**/
public class MyAspect {public void start(){System.out.println("start----");}public void end(){System.out.println("end----");}
}
1、使用动态代理实现对一个方法进行改造
package com.zjp.proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;import com.zjp.aspect.MyAspect;
import com.zjp.dao.UserDao;/*** 动态代理的实现* @author zhujunpeng**/
public class MyProxy implements InvocationHandler{// 需要代理的对象private UserDao userDao;/*** 创建代理方法* @param userDao* @return*/public Object createProxy(UserDao userDao){this.userDao = userDao;// 1、类型加载器ClassLoader classLoader = MyProxy.class.getClassLoader();// 2、被代理对象实现的接口Class>[] clazz = userDao.getClass().getInterfaces();// 3、使用代理类、进行增强,返回的是代理后的对象return Proxy.newProxyInstance(classLoader, clazz, this);}/*** 每个代理对象都会走这个方法*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 声明切面MyAspect myAspect = new MyAspect();myAspect.start();Object object = method.invoke(userDao, args);myAspect.end();return object;}}
增加测试方法
package com.zjp;import com.zjp.dao.UserDao;
import com.zjp.dao.impl.UserDaoImpl;
import com.zjp.proxy.MyProxy;/*** 测试方法* @author zhujunpeng**/
public class JdkProxyTest {public static void main(String[] args) {// 创建代理对象MyProxy myProxy = new MyProxy();UserDao userDao = new UserDaoImpl();userDao.addUser();UserDao userDaoProxy = (UserDao) myProxy.createProxy(userDao);userDaoProxy.addUser();}
}
最后得到的结果为:
public class PersonServerImpl {public void save() {System.out.println("我是save方法");}public String getPersonName() {System.out.println("我是getPersonName方法");return "XX";}public void update() {System.out.println("我是update方法");}}
使用CGLib进行代理
package com.zjp.proxy;import java.lang.reflect.Method;import com.zjp.aspect.MyAspect;
import com.zjp.dao.impl.PersonServerImpl;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;/*** 使用cglib实现动态代理* * @author zhujunpeng**/
public class CglibProxyFactory implements MethodInterceptor {// 需要代理的对象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 {MyAspect aspect = new MyAspect();aspect.start();Object invoke = method.invoke(delegate, args);aspect.end();return invoke;}}
代理类搞定之后,进行测试:
@Testpublic void proxyTest2() {CglibProxyFactory factory = new CglibProxyFactory();PersonServerImpl personServer = new PersonServerImpl();PersonServerImpl personServerProxy = (PersonServerImpl) factory.createProxyInstance(personServer);personServerProxy.save();}
通过测试之后也能实现与Proxy同样的功能。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
