前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式之动态代理模式实战

设计模式之动态代理模式实战

作者头像
Java技术栈
发布2018-03-29 17:42:07
6320
发布2018-03-29 17:42:07
举报
文章被收录于专栏:Java技术栈Java技术栈

昨天分享了静态代理的概念及存在的缺点,所以今天讲的动态代理模式十分重要。动态代理在我们工作当中应用相当广泛,如Srping AOP就是动态代理的在开源框架的比较出名的应用。

动态代理有两种试,一是通过JDK自带的API实现动态代理,二是通过别的字节码框架实现,如cglib。

需要注意的是JDK只能针对接口实现动态代理,不能代理普通类,使用具有局限性。而cglib可以代理接口及所有的普通类。

下面拿昨天保存用户信息的例子继续用动态代理来实现。

用户接口

public interface UserInterface {

boolean saveUser(User user);

}

用户接口实现

public class UserInterfaceImpl implements UserInterface {

@Override

public boolean saveUser(User user) {

System.out.println("保存用户: " + user.getName());

return true;

}

}

public class Test {

public static void main(String[] args) {

// JDK动态代理

testJDKProxy();

// Cglib接口代理

testCglibInterfaceProxy();

// Cglib类代理

testCglibClassProxy();

}

private static void testJDKProxy() {

User user = new User();

user.setName("tom");

UserProxy.getUserProxy().saveUser(user);

}

static class UserProxy {

private static final InvocationHandler USER_HANDLE = new InvocationHandler() {

@Override

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

System.out.println("JDK接口动态代理-开始保存用户");

Object result = method.invoke(new UserInterfaceImpl(), args);

System.out.println("JDK接口动态代理-保存用户结果: " + result);

System.out.println();

return result;

}

};

public static UserInterface getUserProxy() {

UserInterface userInterface = (UserInterface) Proxy.newProxyInstance(UserProxy.class.getClassLoader(),

new Class[] { UserInterface.class }, USER_HANDLE);

return userInterface;

}

}

private static void testCglibInterfaceProxy() {

User user = new User();

user.setName("tom");

UserCglibProxy.getUserProxy().saveUser(user);

}

static class UserCglibProxy {

private static final net.sf.cglib.proxy.InvocationHandler USER_HANDLE = new net.sf.cglib.proxy.InvocationHandler() {

@Override

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

System.out.println("Cglib接口动态代理-开始保存用户");

Object result = method.invoke(new UserInterfaceImpl(), args);

System.out.println("Cglib接口动态代理-保存用户结果: " + result);

System.out.println();

return result;

}

};

public static UserInterface getUserProxy() {

UserInterface userInterface = (UserInterface) net.sf.cglib.proxy.Proxy.newProxyInstance(

UserCglibProxy.class.getClassLoader(), new Class[] { UserInterface.class }, USER_HANDLE);

return userInterface;

}

}

private static void testCglibClassProxy() {

User user = new User();

user.setName("tom");

UserInterfaceImpl userImpl = (UserInterfaceImpl) ClassCgLibProxy.getUserProxy(new UserInterfaceImpl());

userImpl.saveUser(user);

}

static class ClassCgLibProxy {

private static final MethodInterceptor USER_HANDLE = new MethodInterceptor() {

@Override

public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {

System.out.println("Cglib类动态代理-开始保存用户");

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

System.out.println("Cglib类动态代理-保存用户结果: " + result);

System.out.println();

return result;

}

};

public static Object getUserProxy(Object target) {

Enhancer enhancer = new Enhancer();

enhancer.setSuperclass(target.getClass());

enhancer.setCallback(USER_HANDLE);

return enhancer.create();

}

}

}

结果输出:

JDK接口动态代理-开始保存用户

保存用户: tom

JDK接口动态代理-保存用户结果: true

Cglib接口动态代理-开始保存用户

保存用户: tom

Cglib接口动态代理-保存用户结果: true

Cglib类动态代理-开始保存用户

保存用户: tom

Cglib类动态代理-保存用户结果: true

从例子看出,使用也并不复杂,动态代理与静态代理最主要的区别在于,静态代理是编译期间就确定好的代理关系,而动态代理是运行期间由JVM通过反射等技术生成的代理对象,不存在class文件,代理类与被代理类之间的关系是继承关系,所以,普通类final的方法是不能被动态代理的。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-06-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java技术栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档