内容简介:设计模式之动态代理
一、动态代理概念
动态代理分为JDK动态代理和cglib动态代理两种方式。JDK动态代理是由 Java 内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。
总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。
还有一点必须注意: JDK动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,JDK动态代理不能应用。
由此可以看出,JDK动态代理有一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。
二、JDK动态代理
以下代码使用代理模式实现一个大小写字符转换的功能。
定义接口和实现类:
ISomeService接口:
package com.ietree.basicskill.designpattern.dynamicproxy.jdk;
/**
* 接口类
*
* @author Root
*/
public interface ISomeService {
String doFirst();
void doSecond();
}
SomeServiceImpl实现类:
package com.ietree.basicskill.designpattern.dynamicproxy.jdk;
/**
* 实现类
*
* @author Root
*/
public class SomeServiceImpl implements ISomeService {
@Override
public String doFirst() {
System.out.println("执行doFirst()...");
String result = "abcde";
return result;
}
@Override
public void doSecond() {
System.out.println("执行doSecond()...");
}
}
JDK动态代理类:
package com.ietree.basicskill.designpattern.dynamicproxy.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
final ISomeService target = new SomeServiceImpl();
// 使用JDK的Proxy动态代理,要求目标类和代理类必须实现相同的接口,因为其底层的执行原理与静态代理的相同
ISomeService service = (ISomeService) Proxy.newProxyInstance(
// 目标类的类加载器
target.getClass().getClassLoader(),
// 目标类所实现的所有接口
target.getClass().getInterfaces(),
new InvocationHandler() {
// proxy:代理对象
// method:目标方法
// args:目标方法的参数列表
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 调用目标方法
Object result = method.invoke(target, args);
if (result != null) {
result = ((String) result).toUpperCase();
}
return result;
}
});
String result = service.doFirst();
System.out.println(result);
service.doSecond();
}
}
三、cglib动态代理
Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用CGLIB即使代理类没有实现任何接口也可以实现动态代理功能。CGLIB具有简单易用,它的运行速度要远远快于JDK的Proxy动态代理:
CGLIB的核心类:
net.sf.cglib.proxy.Enhancer – 主要的增强类
net.sf.cglib.proxy.MethodInterceptor – 主要的方法拦截类,它是Callback接口的子接口,需要用户实现
net.sf.cglib.proxy.MethodProxy – JDK的java.lang.reflect.Method类的代理类,可以方便的实现对源对象方法的调用,如使用:
Object o = methodProxy.invokeSuper(proxy, args);//虽然第一个参数是被代理对象,也不会出现死循环的问题。
net.sf.cglib.proxy.MethodInterceptor接口是最通用的回调(callback)类型,它经常被基于代理的AOP用来实现拦截(intercept)方法的调用。这个接口只定义了一个方法
public Object intercept(Object object, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable;
第一个参数是代理对像,第二和第三个参数分别是拦截的方法和方法的参数。原来的方法可能通过使用java.lang.reflect.Method对象的一般反射调用,或者使用 net.sf.cglib.proxy.MethodProxy对象调用。net.sf.cglib.proxy.MethodProxy通常被首选使用,因为它更快。
以下程序实现了大小写转换的功能:
实现类SomeService:
package com.ietree.basicskill.designpattern.dynamicproxy.cglib;
/**
* 实现类
*
* @author Root
*/
public class SomeService {
public String doFirst() {
System.out.println("执行doFirst()...");
String result = "abcde";
return result;
}
public void doSecond() {
System.out.println("执行doSecond()...");
}
}
代理类MyCglibFactory:
package com.ietree.basicskill.designpattern.dynamicproxy.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 MyCglibFactory implements MethodInterceptor {
private SomeService target;
public MyCglibFactory() {
super();
target = new SomeService();
}
public SomeService myCglibCreator() {
// 创建增强器对象
Enhancer enhancer = new Enhancer();
// 指定目标类,即父类
enhancer.setSuperclass(SomeService.class);
// 设置回调接口对象
enhancer.setCallback(this);
return (SomeService) enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 调用目标方法
Object result = method.invoke(target, args);
if (result != null) {
result = ((String) result).toUpperCase();
}
return result;
}
}
测试:
package com.ietree.basicskill.designpattern.dynamicproxy.cglib;
public class Main {
public static void main(String[] args) {
SomeService service = new MyCglibFactory().myCglibCreator();
String result = service.doFirst();
System.out.println("result = " + result);
service.doSecond();
}
}
运行结果:
执行doFirst()... result = ABCDE 执行doSecond()...
本文永久更新链接地址 : http://www.linuxidc.com/Linux/2017-06/144642.htm
以上所述就是小编给大家介绍的《设计模式之动态代理》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 设计模式——订阅模式(观察者模式)
- 设计模式-简单工厂、工厂方法模式、抽象工厂模式
- java23种设计模式-门面模式(外观模式)
- 设计模式-享元设计模式
- Java 设计模式之工厂方法模式与抽象工厂模式
- JAVA设计模式之模板方法模式和建造者模式
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
微信民族志、自媒体时代的知识生产与文化实践
赵旭东 / 中国社会科学出版社 / 2017-9 / 98.00元
进入二十一世纪以来,随着网络技术的发展,自媒体的悄然登场深度影响着我们的日常生活。中国社会中自媒体通讯方式的普及以及随之而有的一种文化书写的新形式——微信民族志的出现使原有文化秩序中时空意义发生转变的同时,也在重新塑造着以研究异文化为己任的人类学学科自身的成长、转型与发展。在此种情境之下,由中国人民大学人类学研究所、中国人民大学国家发展与战略研究院、中国人民大学社会学理论与方法研究中心、《探索与争......一起来看看 《微信民族志、自媒体时代的知识生产与文化实践》 这本书的介绍吧!