代理分为静态代理和动态代理,采用代理是为了通过不修改源代码的情况下给程序动态统一添加功能,利用代理技术可以将业务逻辑中一些非业务逻辑的代码分离出来,把他们独立到业务逻辑类外,比如日志记录,性能统计,安全控制,事务处理,异常处理等。这样做,不仅降低了业务逻辑和非业务逻辑的耦合性,提高程序的可重用性,同时提高了开发的效率。
下面以添加日志记录为例,分析静态代理的使用。创建一个用户管理类UserManagerImpl,并创建添加用户方法addUser,为其良好扩展性,创建一个通用接口UserManager,代码分别如下:
接口代码:
- packagecom.snail.pattern;
- publicinterfaceUserManager{
- publicvoidaddUser(StringuserId,StringuserName);
- }
实现类代码:
- packagecom.snail.pattern;
- publicclassUserManagerImplimplementsUserManager{
- publicvoidaddUser(StringuserId,StringuserName){
- try{
- System.out.println("HelloWorld!");
- }catch(Exceptione){
- e.printStackTrace();
- thrownewRuntimeException();
- }
- }
- }
从代码可以看出,注释里面的日志内容和业务逻辑毫无关系,无形中使耦合性增加,如果很多类中需要添加这些日志代码,工作量不言而喻,修改起来也非常麻烦。如果采用静态代理把打印日志的代码抽取到代理类中,通过代理类和业务逻辑类继承自同一个父类,客户端直接调用代理类完成需求,这样就解决了客户端与业务逻辑类的耦合。示例代码如下:
- packagecom.snail.pattern;
- publicclassUserManagerImplProxyimplementsUserManager{
- privateUserManageruserManager;
- publicUserManagerImplProxy(UserManageruserManager){
- this.userManager=userManager;
- }
- @Override
- publicvoidaddUser(StringuserId,StringuserName){
- try{
- System.out.println("开始执行");
- userManager.addUser(userId,userName);
- System.out.println("执行成功!");
- }catch(Exceptione){
- e.printStackTrace();
- System.out.println("执行失败!");
- }
- }
- }
客户端调用代码如下:
- packagecom.snail.pattern;
- publicclassClient{
- publicstaticvoidmain(String[]args){
- UserManageruserManager=newUserManagerImplProxy(newUserManagerImpl());
- userManager.addUser("0111","张三");
- }
- }
静态代理虽隔离了与业务逻辑无关的代码,降低了耦合,让业务逻辑类更专注于业务逻辑,但无法减少代码量,系统重复代码过多,加大了程序员工作量。因此,JDK动态代理完美解决了此问题,动态代理支持在系统运行期给类动态添加代理,然后通过操控代理类完成对目标类的调用。
继续演化上面举的例子,将静态代理改为动态代理,抽象类UserManager和目标类UserManagerImpl中的代码不变,将静态代理类UserManagerImplProxy删除,添加LoadHandler类,并让它实现InvocationHandler接口中的invoke方法,代码如下:
- packagecom.snail.pattern;
- importjava.lang.reflect.InvocationHandler;
- importjava.lang.reflect.Method;
- importjava.lang.reflect.Proxy;
- publicclassLogHandlerimplementsInvocationHandler{
- privateObjecttargetObject;
- publicObjectnewProxyInstance(ObjecttargetObject){
- this.targetObject=targetObject;
- returnProxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),this);
- }
- @Override
- publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)
- throwsThrowable{
- System.out.println("开始执行!");
- for(inti=0;i<args.length;i++){
- System.out.println(args[i]);
- }
- Objectret=null;
- try{
- ret=method.invoke(targetObject,args);
- System.out.println("执行成功!");
- }catch(Exceptione){
- e.printStackTrace();
- System.out.println("执行失败!");
- throwe;
- }
- returnret;
- }
- }
Proxy类所创建的目标类必须实现至少一个接口,在调用newProxyInstance方法时必须与目标类的类加载器和接口一致;invoke方法非常类似Filter中的doFilter方法,它将调用目标类的所有方法在未到达UserManagerImpl之前截获,根据我们自己的需求进行预处理后,继续调用UserManagerImpl。
为了保持invoke方法的通用性,目标方法中的参数以数组args形式传递,如果方法中有返回值,则返回,没有返回值,则返回null。如此一来,程序员不必为每个目标类设计一个代理类,所有需要打印日志的类都可以共用这个LogHandler,如果不想使用日志功能就可以直接删除LogHandler类,对原功能没有丝毫影响,如同揭去显示器上的保护膜,不会影响显示器的使用一般。
客户端调用代码如下:
- packagecom.snail.pattern;
- publicclassClient{
- publicstaticvoidmain(String[]args){
- LogHandlerlogHandler=newLogHandler();
- UserManageruserManager=(UserManager)logHandler.newProxyInstance(newUserManagerImpl());
- userManager.addUser("id","name");
- }
- }
分享到:
相关推荐
spring之AOP(动态代理),包括jdk动态代理和CGLib动态代理
主要对Spring AOP的相关概念和简单的静态代理、动态代理以及常见的几种AOP配置方式做总结学习。主要包括:1. AOP的常见概念 2. 静态代理 3. jdk动态代理 4. Aspectj and Aspectjweaver 5. **aop-config** 6. CGLIB ...
AOP的意思就是面向切面编程。本文主要是通过梳理JDK中自带的反射机制,实现 AOP动态代理模式,这也是Spring AOP 的实现原理
AOP动态代理描述了Spring AOP中使用Java高级技术功能实现的动态代理,为Spring IOC等高级开发实现了逻辑功能;
反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)
AOP之JDK动态代理和CGLib动态代理 ,具体效果和过程看博文 http://blog.csdn.net/evankaka/article/details/45195383
介绍AOP动态代理很不错的一本技术书籍,里面又很多例子通俗易懂。
动态代理实现AOP机制,动态代理实现AOP机制,动态代理实现AOP机制,动态代理实现AOP机制
springAOP配置实现动态代理,有利于熟悉动态代理原理,深入了解spring。
1. 首先完成一个接口的创建(里面有真正的想要实现的方法): public interface UserDAO{ public void add (); //想要实现的方法 } 2. 写一个真实的主题类实现...3. 写一个动态的代理类实现InvocationHandler接口:
AOP 动态代理demo,AOP 动态代理demo
SpringAOP动态代理 Spring AOP 使用的动态代理主要有两种方式:JDK 动态代理和 CGLIB 代理。 JDK 动态代理:用于代理实现了接口的类。Spring 会使用 java.lang.reflect.Proxy 类来创建代理对象。 CGLIB 代理:用于...
jdk动态代理--适合企业级开发,但是它要求必须面向接口编程,假如目标类没有实现接口,则没办法代理这个类。 cglib代理, 1.cglib(Code Generation Library)是一个强大的,高性能,高质量的Code生成类库。它可以在...
为了说明Spring的AOP原理,本人使用代理模式中的动态代理完成演示AOP编程的原理的演示。相信,如果你耐心看完整个程序(几乎一行注释一行代码),那么你对Spring这个东西就不是觉得有什么神秘了! 阅读对象:凡是喜爱...
死磕Spring之AOP篇 - Spring AOP两种代理对象的拦截处理(csdn)————程序
用Java动态代理实现AOP,讲的很好(用Java动态代理实现AOP)
随着软件技术的发展及需求的增加,OOP逐渐表现出其不足之处,AOP在继承OOP基础之上很好地解决了00P 所面临的困难。针对OOP编程思想的一种补充,AOP编程思想通过分离出与系统核心业务实现无关的模块,减少模块 问的...
通过动态代理模拟Spring AOP,通过动态代理模拟Spring AOP
本资源利用文档加源码的方式较详细的介绍了JDK 动态代理和Spring的AOP机制.相信对您理解相关方面的知识有很大作用.
package com.gc.dynproxy下为:aop方式动态代理 package com.gc.javaproxy下为:java代理机制实现 package com.gc.proxy下为:自定义代理模式(面向接口编程) package com.gc.normal下为:通用日志处理方式