代理模式()
动态代理介绍
动态代理是指在运行时动态生成代理类即代理类的字节码将在运行时生成并载入当前的ClassLoader与静态代理类相比动态类有诸多好处首先不需要为真实主题写一个形式上完全一样的封装类假如主题接口中的方法很多为每一个接口写一个代理方法也是非常烦人的事如果接口有变动则真实主题和代理类都要修改不利于系统维护其次使用一些动态代理的生成方法甚至可以在运行时指定代理类的执行逻辑从而大大提升系统的灵活性
注意动态代理使用字节码动态生成加载技术在运行时生成并加载类
生成动态代理类的方法很多如JDK自带的动态代理CGLIBJavassist或者ASM库JDK的动态代理使用简单它内置在JDK中因此不需要引入第三方Jar包但相对功能比较弱CGLIB和Javassist都是高级的字节码生成库总体性能比JDK自带的动态代理好而且功能十分强大ASM是低级的字节码生成工具使用ASM已经近乎于在使用Java bytecode编程对开发人员要求最高当然也是性能最好的一种动态代理生成工具但ASM的使用实在过于繁琐而且性能也没有数量级的提升与CGLIB等高级字节码生成工具相比ASM程序的可维护性也较差如果不是在对性能有苛刻要求的场合笔者还是推荐CGLIB或者Javassist
动态代理实现
以上例中的DBQueryProxy为例使用动态代理生成动态类替代上例中的DBQueryProxy首先使用JDK的动态代理生成代理对象JDK的动态代理需要实现一个处理方法调用的Handler用于实现代理方法的内部逻辑
public class JdkDbQeuryHandler implements InvocationHandler {
IDBQuery real=null; //主题接口
@Override
public Object invoke(Object proxy Method method Object[] args)
throws Throwable {
if(real==null)
real=new DBQuery() //如果是第一次调用则生成真实对象
return realrequest() //使用真实主题完成实际的操作
}
}
以上代码实现了一个Handler可以看到它的内部逻辑和DBQueryProxy是类似的在调用真实主题的方法前先尝试生成真实主题对象接着需要使用这个Handler生成动态代理对象
public static IDBQuery createJdkProxy(){
IDBQuery jdkProxy = (IDBQuery) ProxynewProxyInstance(
ClassLoadergetSystemClassLoader()
new Class[] { IDBQueryclass }
new JdkDbQeuryHandler()) //指定Handler
return jdkProxy;
}
以上代码生成一个实现了IDBQuery接口的代理类代理类的内部逻辑由JdkDbQeuryHandler决定生成代理类后由newProxyInstance()方法返回该代理类的一个实例至此一个完整的JDK动态代理就完成了
CGLIB和Javassist的动态代理的使用和JDK的动态代理非常类似下面尝试使用CGLIB生成动态代理CGLIB也需要实现一个处理代理逻辑的切入类
public class CglibDbQueryInterceptor implements MethodInterceptor {
IDBQuery real=null;
@Override
public Object intercept(Object arg Method arg Object[] arg
MethodProxy arg) throws Throwable {
if(real==null) //代理类的内部逻辑
//和前文中的一样
real=new DBQuery()
return realrequest()
}
}
返回目录Java程序性能优化让你的Java程序更快更稳定
编辑推荐
Java程序设计培训视频教程
JEE高级框架实战培训视频教程
JME移动开发实战教学视频
Visual C++音频/视频技术开发与实战
Oracle索引技术
ORACLEG数据库开发优化指南