java设计优化--代理模式
代理模式使用代理对象完成用户的请求,屏蔽用户对真实对象的访问。
代理模式的用途很多,比如因为安全原因,需要屏蔽客户端直接访问真实对象;或者在远程调用中,需要使用代理对象处理远程方法中的技术细节;或者为了提升系统,对真是对象进行封装,从而达到延迟加载的目的。
在系统启动时,将消耗资源最多的方法使用代理模式分离,就可以加快系统的启动速度,减少用户的等待时间。在用户真正在做查询是,再由代理类加载真实的类,完成用户请求。这就是使用代理模式达到延迟加载的目的。
1.静态代理实现:
主题接口:
1 public interface IDBQuery { 2 String request(); 3 }
真实主题:
1 public class DBQuery implements IDBQuery { 2 public DBQuery(){ 3 try { 4 Thread.sleep(10000); 5 } catch (Exception e) { 6 e.printStackTrace(); 7 } 8 } 9 public String request() { 10 return "string request"; 11 } 12 }
代理类:
1 public class IDBQueryProxy implements IDBQuery { 2 private DBQuery dbquery; 3 public String request() { 4 if(dbquery==null) 5 dbquery = new DBQuery(); 6 return dbquery.request(); 7 } 8 }
最后,主函数:
1 public class ProxyText { 2 public static void main(String[] args) { 3 IDBQuery dbquery = new IDBQueryProxy(); 4 System.out.println(dbquery.request()); 5 } 6 }
静态代理注意,代理类是真实类实现共同的接口,并且代理类引用真实类对象,将耗时操作放在代理类方法中实现。
动态代理:
动态代理即运行时,动态生成代理类。即:代理类的字节码在运行时生成并载入当前的classloader。与静态代理相比,动态代理不需要为真实注意封装一个形式上完全一样的封装类,假如主题接口很多,就要为每一个接口写一个代理方法是很烦人的,如果接口有变动,真实类和代理类都需要变化,这样不利于系统维护;其次,使用一些动态代理的生成方法甚至可以在运行是指定代理类的执行逻辑,从而大大提高的系统的灵活性。
主题接口:
1 public interface IDBQuery { 2 String request(); 3 }
jdk代理类:
1 public class JdbDbqueryHandler implements InvocationHandler{ 2 IDBQuery idbquery = null; 3 @Override 4 public Object invoke(Object proxy, Method method, Object[] args) 5 throws Throwable { 6 if(idbquery==null){ 7 idbquery = new DBQuery(); 8 } 9 return idbquery.request(); 10 } 11 public static IDBQuery createJdbProxy(){ 12 IDBQuery jdkProxy = (IDBQuery) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), 13 new Class[]{IDBQuery.class}, new JdbDbqueryHandler()); 14 System.out.println("JdbDbqueryHandler.createJdbProxy()"); 15 return jdkProxy; 16 } 17 18 }
主函数:
1 public class ProxyText { 2 public static void main(String[] args) { 3 IDBQuery idbQuery = JdbDbqueryHandler.createJdbProxy(); 4 System.out.println(idbQuery.request()); 5 } 6 }
另外,也可以使用CGLIB和javassist动态代理与jdk动态代理类似,但是jdk动态类的创建过程最快,因为这个内置实现的difineclass()方法被定义为native实现,故性能优于其他。在代理类的函数调用上,JDK的动态代理不如CGLIB和javassist动态代理,而javassist动态代理性能质量最差,甚至不如JDK的实现。在实际开发应用中,代理类的方法调用频率要远远高于代理类的实际生成频率,故动态代理的方法调用性能应该成为性能的关注点。JDK动态代理强制要求代理类和真是主题实现统一接口,CGLIB和javassist动态代理没有这样的要求。
在java中,动态代理的实现涉及到classloader的使用,以CGLIB为例,简要描述下动态类的加载过程。使用CGLIB生成动态代理,首先需要生成Enhancer类的实例,并制定用于处理代理业务的回调类。在enhancer.create()方法中,会使用DefaultGeneratorStrategy.Generate()方法生成代理类的字节码,并保存在byte数组中。接着调用reflectUtils.defineClass()方法,通过反射,调用ClassLoader.defineClass()方法,将字节码装载到classloader中,完成类的加载。最后,通过reflectUtils.newInstance()方法,通过反射生成动态类实例,并返回该实例。其他与该过程细节不同,但是生成逻辑相同。
相关文章
- 【Java学习笔记】设计模式——代理模式(Proxy)
- Effective Java 第三版—— 90.考虑序列化代理替代序列化实例
- Java学习笔记——File类文件管理及IO读写、复制操作
- Java 反射&&动态代理,面试官听了都爱了
- java动态代理
- java设计模式----代理模式
- Java学习笔记之Java环境配置
- [转载]Java中继承、装饰者模式和代理模式的区别
- Java设计模式(10)——结构型模式之代理模式(Proxy)
- java 动态代理(类型信息)
- java之vector详细介绍
- 详解java动态代理机制以及使用场景
- Java动态代理机制详解(类加载,JDK 和CGLIB,Javassist,ASM)
- JAVA 设计模式 代理模式
- JAVA设计模式之【代理模式】
- Java SE之正则表达式三:替换
- java读取文件
- java 代理模式详解【转】
- request url /product/onShelf method PUT cause by JSON parse error: Cannot deserialize instance of `java.util.ArrayList<com.efivestar.training.model.dto.product.ProductOnShelfReqDTO>`
- 【Java设计模式——代理模式】
- Java 为什么需要用到代理
- SpringAOP专题之1、代理详解(java动态代理&CGLIB代理)
- 【java web篇】MyBatis之Mapper代理
- Java常量定义需要注意事项及static作用(复习)
- Java的三种代理模式
- 【JAVA长虹键法】第八式 代理模式(23种设计模式)
- JAVA随机生成指定长度的一串密码