参考来自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html

1.代理模式

 代理类和委托类有相同接口。
代理类负责为委托类:预处理消息
过滤消息
把消息转发给委托类
事后处理消息等
代理类和委托类会相关联。
代理类不真正实现服务,而是通过调用委托类的相关方法,来提供服务。

2.代理的分类

 静态代理:由程序员创建,或者由特定工具自动生成源代码,再对其编译。在运行之前,代理类的.class文件就存在了。
动态代理:在程序运行时,根据java的反射机制动态创建。
  3 jdk动态代理:委托类必须实现接口
  4 Cglib动态代理:委托类不用实现接口,针对类

2.1 静态代理

(1)实例
 public interface Count {
// 查看账户方法
public void queryCount();
// 修改账户方法
public void updateCount();
}
 public class CountImpl implements Count {  

     @Override
public void queryCount() {
System.out.println("查看账户方法...");
} @Override
public void updateCount() {
System.out.println("修改账户方法...");
}
}

创建一个代理类,可以看到CountProxy和CountImpl实现了同样的接口:Count。

 public class CountProxy implements Count {
private CountImpl countImpl; /**
* 覆盖默认构造器
*
* @param countImpl
*/
public CountProxy(CountImpl countImpl) {
this.countImpl = countImpl;
} @Override
public void queryCount() {
System.out.println("事务处理之前");
// 调用委托类的方法;
countImpl.queryCount();
System.out.println("事务处理之后");
} @Override
public void updateCount() {
System.out.println("事务处理之前");
// 调用委托类的方法;
countImpl.updateCount();
System.out.println("事务处理之后");
} }
(2)测试

由测试可知,采用constructor关联起来的proxy和impl,必须是1对1的,十分低效。

 public class TestCount {
public static void main(String[] args) {
CountImpl countImpl = new CountImpl();
CountProxy countProxy = new CountProxy(countImpl);
countProxy.updateCount();
countProxy.queryCount();
}
}

显然,通过上面的代码可以知道,这样的代理类只能为一个接口服务,会产生过多的代理类。而且所有的代理类中除了调用的方法不一样,其他操作都一样,重复代码过多。为了使用一个代理类来完成全部的代理功能,显然不能在运行前就生成好代理类的.class文件。即,必须使用动态代理。

2.2 JDK动态代理

(1)interface InvocationHandler
 public interface InvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}

参数说明:

 Object proxy:指代理的对象。
Method method:要调用的方法
Object[] args:方法调用时所需要的参数
(2)class Proxy

java.lang.reflect.Proxy类提供了一个方法:newProxyInstance。

 public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)  throws IllegalArgumentException 

参数说明:

1 ClassLoader loader:类加载器
2 Class<?>[] interfaces:得到全部的接口
3 InvocationHandler h:得到InvocationHandler接口的子类实例
(3)实例
 1 public interface BookFacade {
2 public void addBook();
3 }
4
5 public class BookFacadeImpl implements BookFacade {
6
7 @Override
8 public void addBook() {
9 System.out.println("增加图书方法。。。");
10 }
11 }
 import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class BookFacadeProxy implements InvocationHandler {
private Object target;
/**
* 绑定委托对象并返回一个代理类
* @param target 委托对象
* @return 代理类
*/
public Object bind(Object target) {
this.target = target;
//取得代理对象 //要绑定接口(这是一个缺陷,cglib弥补了)
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
16   target.getClass().getInterfaces(),
17         this);
} @Override
/**
* 调用委托类的方法
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result=null;
System.out.println("事物开始");
//执行方法
result=method.invoke(target, args);
System.out.println("事物结束");
return result;
}
}
(4)测试

由测试可知,此时只需要一个代理类,就可以通用了。但是,JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。

 public class TestProxy {  

     public static void main(String[] args) {
BookFacadeProxy proxy = new BookFacadeProxy();
BookFacade bookProxy = (BookFacade) proxy.bind(new BookFacadeImpl());
bookProxy.addBook();
}
}

2.3 Cglib动态代理

由前面可知,当委托类并没有实现某个接口(implements someInterface)时,jdk动态代理就不能使用了。

cglib是针对类来实现代理(没有实现某个接口也不会造成影响),原理:对委托类生成一个子类(局限:final),并覆盖其中方法实现增强

(1)实例
 public class BookFacadeImpl1 {  //没有implements BookFacade
public void addBook() {
System.out.println("增加图书的普通方法...");
}
}
 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 BookFacadeCglib implements MethodInterceptor {
private Object target; /**
* 创建代理对象 * @param target 委托类
* @return 代理类
*/
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
} @Override
// 回调方法
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("事物开始");
proxy.invokeSuper(obj, args);
System.out.println("事物结束");
return null;
}
}
(2)测试
 public class TestCglib {  

     public static void main(String[] args) {
BookFacadeCglib cglib=new BookFacadeCglib();
BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1());
bookCglib.addBook();
}
}

3.总结

 静态代理缺点:代码一对一,重复冗余,编译时就需要存在代理类的.class文件。
动态代理优点:动态生成,统一处理,运行时生成代理类。
jdk动态代理: Proxy,InvocationHandler
cglib动态代理:MethodInterceptor

2017.5.1 java动态代理总结的更多相关文章

  1. java动态代理实现与原理详细分析

    关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式    代理模式是常用的java设计模式, ...

  2. java动态代理实现与原理详细分析(转)

    关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式    代理模式是常用的java设计模式, ...

  3. Java 动态代理机制详解

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  4. Java动态代理全面分析

    代理模式 解说:给某一个对象提供一个代理,并由代理对象控制对原对象的引用: 代理模式需要以下几个角色: 1  主题:规定代理类和真实对象共同对外暴露的接口: 2  代理类:专门代理真实对象的类: 3 ...

  5. JAVA动态代理模式(从现实生活角度理解代码原理)

    所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect包中的两个 ...

  6. Java 动态代理作用是什么?

    Java 动态代理作用是什么?   1 条评论 分享   默认排序按时间排序 19 个回答 133赞同反对,不会显示你的姓名 Intopass 程序员,近期沉迷于动漫ING 133 人赞同 ① 首先你 ...

  7. java动态代理原理

    我们经常会用到Java的动态代理技术, 虽然会使用, 但是自己对其中的原理却不是很了解.比如代理对象是如何产生的, InvocationHandler的invoke方法是如何调用的?今天就来深究下Ja ...

  8. java 动态代理示例,带主要注释

    Java proxy是基于反射,仅仅支持基于接口的动态代理. java 动态代理是一切架构的基础,必须了解. 废话少说,先上代码获得感性认识. 示例代码有主要注释. 接口: public interf ...

  9. java动态代理浅析

    最近在公司看到了mybatis与spring整合中MapperScannerConfigurer的使用,该类通过反向代理自动生成基于接口的动态代理类. 于是想起了java的动态代理,然后就有了这篇文章 ...

随机推荐

  1. idea创建maven项目需要注意的问题

    idea创建maven项目之后,我从deployment中看到报部署错误的问题,下图是解决问题的办法如下图所示:

  2. navicat for mysql 2003错误

    最近又一次碰到navicat for mysql 2003错误,之前碰到好几次了,问题再次出现还是有些不知所措,所以记下来,再次遇到时就可以迎韧有余了. 解决方案1: 重启防火墙:关闭再重新开启. 解 ...

  3. 洛谷P3120 [USACO15FEB]Cow Hopscotch

    题目描述 Just like humans enjoy playing the game of Hopscotch, Farmer John&apos;s cows have invented ...

  4. 【ZOJ4070】Function and Function(签到)

    题意:求 k 层嵌套的 f(x) 0<=x,k<=1e9 思路:迭代不会很多次后函数里就会=0或者1,再看层数奇偶直接返回答案 #include<cstdio> #includ ...

  5. Android 画笔Paint

    转自 http://wuxiaolong.me/2016/08/20/Paint/ 了解Android Paint,一篇就够.引用Aige<自定义控件其实很简单>系列博客的话“很多时候你压 ...

  6. C++中的 Round(),floor(),ceil()

     2.1             2.6               -2.1               -2.6floor : 不大于自变量的最大整数             2          ...

  7. [LeetCode] Evaluate Reverse Polish Notation stack 栈

    Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, ...

  8. 【原创】Linux环境下的图形系统和AMD R600显卡编程(10)——R600显卡的3D引擎编程

    3D图形处理流水线需要流经多个硬件单元才能得到最后的渲染结果,流水线上的所有的硬件单元必须被正确编程,才能得到正确的结果. 总体上看,从图形处理流水线的源头开始,需要准备好vertex和index,在 ...

  9. 使用vim进行java编程

    首先:编写源代码Test.java 1class Test{                                                                       ...

  10. Linux SPI总线和设备驱动架构之一:系统概述【转】

    转自:http://blog.csdn.net/droidphone/article/details/23367051/ 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[-] 硬 ...