Java 动态代理(转载)
JAVA的动态代理 
代理模式 
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后
处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的
对象的相关方法,来提供特定的服务。 
按照代理的创建时期,代理类可以分为两种。 
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。 
动态代理:在程序运行时,运用反射机制动态创建而成。
首先看一下静态代理: 
1、Count.java
2、CountImpl.java
     package net.battier.dao.impl;  
     import net.battier.dao.Count;  
     /**
      * 委托类(包含业务逻辑)
      *
      * @author Administrator
      *
      */
     public class CountImpl implements Count {  
         @Override
         public void queryCount() {
             System.out.println("查看账户方法...");  
         }  
         @Override
         public void updateCount() {
             System.out.println("修改账户方法...");  
         }  
     }  
     、CountProxy.java
     package net.battier.dao.impl;  
     import net.battier.dao.Count;  
     /**
      * 这是一个代理类(增强CountImpl实现类)
      *
      * @author Administrator
      *
      */
     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("事务处理之后");  
         }  
     }  
3、TestCount.java
     package net.battier.test;  
     import net.battier.dao.impl.CountImpl;
     import net.battier.dao.impl.CountProxy;  
     /**
      *测试Count类
      *
      * @author Administrator
      *
      */
     public class TestCount {
         public static void main(String[] args) {
             CountImpl countImpl = new CountImpl();
             CountProxy countProxy = new CountProxy(countImpl);
             countProxy.updateCount();
             countProxy.queryCount();  
         }
     }  
观察代码可以发现每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理,而且,所有的代理操作除了调用的方法不一样之外,其他 的操作都一样,则此时肯定是重复代码。解决这一问题最好的做法是可以通过一个代理类完成全部的代理功能,那么此时就必须使用动态代理完成。 
再来看一下动态代理: 
JDK动态代理中包含一个类和一个接口: 
InvocationHandler接口: 
public interface InvocationHandler { 
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; 
} 
参数说明: 
Object proxy:指被代理的对象。 
Method method:要调用的方法 
Object[] args:方法调用时所需要的参数
可以将InvocationHandler接口的子类想象成一个代理的最终操作类,替换掉ProxySubject。
Proxy类: 
Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法: 
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, 
InvocationHandler h) 
                               throws IllegalArgumentException 
参数说明: 
ClassLoader loader:类加载器 
Class<?>[] interfaces:得到全部的接口 
InvocationHandler h:得到InvocationHandler接口的子类实例
Ps:类加载器 
在Proxy类中的newProxyInstance()方法中需要一个ClassLoader类的实例,ClassLoader实际上对应的是类加载器,在Java中主要有一下三种类加载器; 
Booststrap ClassLoader:此加载器采用C++编写,一般开发中是看不到的; 
Extendsion ClassLoader:用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类; 
AppClassLoader:(默认)加载classpath指定的类,是最常使用的是一种加载器。
动态代理 
与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程
工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect
包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。
动态代理示例: 
1、BookFacade.java
     package net.battier.dao;  
     public interface BookFacade {
         public void addBook();
     }  
2、BookFacadeImpl.java
     package net.battier.dao.impl;  
     import net.battier.dao.BookFacade;  
     public class BookFacadeImpl implements BookFacade {  
         @Override
         public void addBook() {
             System.out.println("增加图书方法。。。");
         }  
     }  
     、BookFacadeProxy.java  
     package net.battier.proxy;  
     import java.lang.reflect.InvocationHandler;
     import java.lang.reflect.Method;
     import java.lang.reflect.Proxy;  
     /**
      * JDK动态代理代理类
      *
      * @author student
      *
      */
     public class BookFacadeProxy implements InvocationHandler {
         private Object target;
         /**
          * 绑定委托对象并返回一个代理类
          * @param target
          * @return
          */
         public Object bind(Object target) {
             this.target = target;
             //取得代理对象
             return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                     target.getClass().getInterfaces(), this);   //要绑定接口(这是一个缺陷,cglib弥补了这一缺陷)
         }  
         @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;
         }  
     }  
3、TestProxy.java
     package net.battier.test;  
     import net.battier.dao.BookFacade;
     import net.battier.dao.impl.BookFacadeImpl;
     import net.battier.proxy.BookFacadeProxy;  
     public class TestProxy {  
         public static void main(String[] args) {
             BookFacadeProxy proxy = new BookFacadeProxy();
             BookFacade bookProxy = (BookFacade) proxy.bind(new BookFacadeImpl());
             bookProxy.addBook();
         }  
     }  
但是,JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。
Cglib动态代理 
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。 
示例 
1、BookFacadeCglib.java
     package net.battier.dao;  
     public interface BookFacade {
         public void addBook();
     }  
2、BookCadeImpl1.java
     package net.battier.dao.impl;  
     /**
      * 这个是没有实现接口的实现类
      *
      * @author student
      *
      */
     public class BookFacadeImpl1 {
         public void addBook() {
             System.out.println("增加图书的普通方法...");
         }
     }  
3、BookFacadeProxy.java
     package net.battier.proxy;  
     import java.lang.reflect.Method;  
     import net.sf.cglib.proxy.Enhancer;
     import net.sf.cglib.proxy.MethodInterceptor;
     import net.sf.cglib.proxy.MethodProxy;  
     /**
      * 使用cglib动态代理
      *
      * @author student
      *
      */
     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;  
         }  
     }  
4、TestCglib.java
     package net.battier.test;  
     import net.battier.dao.impl.BookFacadeImpl1;
     import net.battier.proxy.BookFacadeCglib;  
     public class TestCglib {  
         public static void main(String[] args) {
             BookFacadeCglib cglib=new BookFacadeCglib();
             BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1());
             bookCglib.addBook();
         }
     }  
动态创建代理类
代理模式:代理模式的作用=为其他对象提供一种代理以控制对这个对象的访问。
代理模式的角色:
抽象角色:声明真实对象和代理对象的共同接口
代理角色:代理角色内部包含有真实对象的引用,从而可以操作真实对象。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
动态代理:
| java.lang.reflect.Proxy | Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类 | 
| InvocationHandler | 是代理实例的调用处理程序 实现的接口,每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。 | 
动态Proxy是这样的一种类:
它是在运行生成的类,在生成时你必须提供一组Interface给它,然后该class就宣 称它实现了这些interface。你可以把该class的实例当作这些interface中的任何一个来用。当然,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。
在使用动态代理类时,我们必须实现InvocationHandler接口
步骤:
1、定义抽象角色
public interface Subject {
public void Request();
}
2、定义真实角色
public class RealSubject implements Subject {
@Override
public void Request() {
// TODO Auto-generated method stub
System.out.println("RealSubject");
}
}
3、定义代理角色
public class DynamicSubject implements InvocationHandler {
private Object sub;
public DynamicSubject(Object obj){
this.sub = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
System.out.println("Method:"+ method + ",Args:" + args);
method.invoke(sub, args);
return null;
}
}
4、通过Proxy.newProxyInstance构建代理对象
RealSubject realSub = new RealSubject();
InvocationHandler handler = new DynamicSubject(realSub);
Class<?> classType = handler.getClass();
Subject sub = (Subject)Proxy.newProxyInstance(classType.getClassLoader(),
realSub.getClass().getInterfaces(), handler);
System.out.println(sub.getClass());
5、通过调用代理对象的方法去调用真实角色的方法。
sub.Request();
输出:
class $Proxy0 新建的代理对象,它实现指定的接口
Method:public abstract void DynamicProxy.Subject.Request(),Args:null
RealSubject 调用的真实对象的方法
Java 动态代理(转载)的更多相关文章
- java动态代理实现与原理详细分析(【转载】By---    Gonjan )
		[转载]By---Gonjan 关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式 ... 
- 【转载】Java 动态代理
		Java 动态代理 本文为 Android 开源项目源码解析 公共技术点中的 动态代理 部分项目地址:Jave Proxy,分析的版本:openjdk 1.6,Demo 地址:Proxy Demo分析 ... 
- Java动态代理 深度详解
		代理模式是设计模式中非常重要的一种类型,而设计模式又是编程中非常重要的知识点,特别是在业务系统的重构中,更是有举足轻重的地位.代理模式从类型上来说,可以分为静态代理和动态代理两种类型. 今天我将用非常 ... 
- 理解java动态代理
		java动态代理是java语言的一项高级特性.在平时的项目开发中,可能很难遇到动态代理的案例.但是动态代理在很多框架中起着不可替代的作用,例如Spring的AOP.今天我们就聊一聊java动态代理的实 ... 
- JAVA动态代理 你真的完全了解Java动态代理吗?
		网上讲JAVA动态代理,说的天花乱坠,发现一篇文章写的通俗易懂,特意转载过来 原文地址:https://www.jianshu.com/p/95970b089360 动态代理看起来好像是个什么高大上的 ... 
- Java 动态代理机制详解
		在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ... 
- Java动态代理全面分析
		代理模式 解说:给某一个对象提供一个代理,并由代理对象控制对原对象的引用: 代理模式需要以下几个角色: 1 主题:规定代理类和真实对象共同对外暴露的接口: 2 代理类:专门代理真实对象的类: 3 ... 
- JAVA动态代理模式(从现实生活角度理解代码原理)
		所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect包中的两个 ... 
- Java 动态代理作用是什么?
		Java 动态代理作用是什么? 1 条评论 分享 默认排序按时间排序 19 个回答 133赞同反对,不会显示你的姓名 Intopass 程序员,近期沉迷于动漫ING 133 人赞同 ① 首先你 ... 
随机推荐
- 在Flex4中使用RemoteObjectAMF0来连接fluorine网关 转
			转http://vipnews.csdn.net/newscontent.aspx?pointid=2011_04_21_142132661 RemoteObjectAMF0是一个开源组件,可以很方便 ... 
- MapReduce的方式进行HBase向HDFS导入和导出
			附录代码: HBase---->HDFS import java.io.IOException; import org.apache.hadoop.conf.Configuration; imp ... 
- 关于hadoop2.4.1伪分布式系统的搭建
			1.准备Linux环境 1.0点击VMware快捷方式,右键打开文件所在位置 -> 双击vmnetcfg.exe -> VMnet1 host-only ->修改subnet ip ... 
- 【memset】关于memset的初始最大最小值
			声明:也是摘自网上各路大神的. memset的正规用法是只能用来初始化char类型的数组的,也就是说,它只接受0x00-0xFF的赋值. 因为char是1字节,memset是按照字节赋值的,相当于把每 ... 
- hdu 4607 树的直径
			思路:利用dfs遍历整棵树,找出最长子树与次长子树,两者的和最大就是直径. 若k值小于直径就输出k-1,否则输出(k-d-1)*2+d; #include<iostream> #inclu ... 
- zoj 2676 网络流+01分数规划
			思路: 这题的结论得要看amber的论文,结论就是将求f(x)/b(x)最小转化为求min(f(x)-b(x)*λ),其中x为S集的解空间,f(x)为解的边权和,b(x)为解的边数, λ=f(x)/b ... 
- EWM Matrai  B2B管理平台
			该应用是一款企业管理的app,可以通过“分享”.“工作分派”.“审批”.“业务”.“工作计划”.“日程”等功能得到有效的管控.该项目主要分为5大模块,分别是近期动态,任务,日程,我,在线聊天. 
- Networking - ARP 协议
			ARP 协议概述 ARP(Address Resolution Protocol),即地址解析协议,用于把 IP 地址映射到物理地址.网段上的每台主机都维护着一个被称为 ARP Table 或 ARP ... 
- Ubuntu系统中登陆阿里云服务器的方法
			如果您购买了阿里云服务器,恰巧又在使用Ubuntu操作系统,那么恭喜你来对地方了,今天给大家分享一下如何在Ubuntu中登陆阿里云服务器: 主要使用两款软件:1.SecureCRT:2.SecureF ... 
- C# winform滚动字幕
			private void timer1_Tick(object sender, EventArgs e)//用Timer来控制滚动速度 { label1.Left -= 2;//设置label1左边缘 ... 
