代理模式的核心思路就是一个接口有两个子类,一个子类完成核心的业务操作,另一个子类完成与核心业务有关的辅助性操作。

代理模式分为静态代理模式和动态代理模式。

 静态代理模式:

//接口类
interface Food{
public void eat();
}
//核心业务操作类
class RealFood implements Food{
@Override
public void eat() {
System.out.println("马小超在吃饭!");
}
}
//与核心业务有关的辅助性操作
class ProxyFood implements Food{
private Food food; public Food bind(Food food){
this.food = food;
return this;
}
@Override
public void eat() {
this.prepare();
this.food.eat();
this.after();
}
private void prepare(){
System.out.println("吃饭钱准备:洗手");
}
private void after(){
System.out.println("吃饭后收拾:洗碗");
}
}
//测试类
public class StaticProxy {
public static void main(String[] args){
Food food = new ProxyFood().bind(new RealFood());
food.eat();
}
}

输出结果:

吃饭钱准备:洗手
马小超在吃饭!
吃饭后收拾:洗碗

如上代码所示,定义一个接口类Food,定义一个实现类RealFood来完成核心业务操作,同时再定义一个代理类ProxyFood来完成与核心业务相关的辅助操作。

在代理类ProxyFood中引入代理对象food,定义辅助操作的方法,在重写的eat()方法中引用辅助操作方法。代码如上面所示。

静态的代理模式都是一个接口两个子类,这样一来就会导致一个类只能为一个接口服务。如果有几十个接口,那项目就别做了,这样的设计有很明显的缺陷。那么怎么样才能解决这个问题了?利用反射就可以解决啦。

动态代理模式:

要实现动态代理,则必须实现反射包中的InvocationHandler接口,该接口中只定义了一个invoke()方法,在代理实例上处理方法调用并返回结果。

Object invoke(Object proxy,Method method,Object[] args)throws Throwable

invoke()方法接受的参数如下:

proxy:需要代理的对象

method:表示真实主体要调用的执行方法

args:调用方法时(上面的method代表的方法)传递的参数

在调用invoke()方法时,所有的真实主体类都需要返回一个代理对象,而这个代理对象由Porxy类中的newProxyInstance方法来完成。

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

该方法返回一个指定接口的代理实例,这个指定接口可以将方法调用指派到指定的调用处理程序。

newProxyInstance需要的参数如下:

loader:定义被代理类的类加载器。

interfaces:被代理类要实现接口列表

h:指派方法调用的调用处理程序,用被代理类的实例创建动态代理类的实例,用于真正调用处理程序

代码如下:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//接口类
interface DaoI{
public void doSave();
public Object getById(String id);
}
//DaoI实现类,真实主体类,即被代理类
class DaoImpl implements DaoI{
@Override
public void doSave() {
System.out.println("执行保存方法【doSave】");
}
@Override
public Object getById(String id) {
System.out.println("执行根据ID查找对象方法【getById】");
return null;
}
}
//InvocationHandler实现类
class DaoProxy implements InvocationHandler{
//被代理类的对象
private Object target; //绑定被代理对象
public Object bind(Object target){
this.target = target;
//返回实现了被代理类所实现的所有接口的Object对象,即动态代理,需要强制转型
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
//日志记录方法
private void log(String method){
System.out.println("进行日志记录,方法为:" + method);
}
//事物提交方法
private void commit(){
System.out.println("事物提交");
} /**
* <p>Discription:覆盖InvocationHandler接口中的invoke()方法</p>
* @param proxy 需要代理的对象
* @param method 真实主体要调用的执行方法
* @param args 调用方法时传递的参数
* @return
* @throws Throwable
* @author : lcma
* @update : 2016年10月9日下午2:46:29
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//日志记录操作
this.log(method.getName());
//使用反射中的invoke()对方法进行动态调用
Object obj = method.invoke(this.target, args);
//过滤出以do开头的方法,该方法对数据库进行修改,进行事物提交操作
if(method.getName().matches("do[a-zA-Z0-9]+")){
this.commit();
}
return obj;
}
}
//测试类
public class AutoProxy {
public static void main(String[] args){
//获得代理的实例
DaoI dao = (DaoI)new DaoProxy().bind(new DaoImpl());
//调用被代理类中的保存方法
dao.doSave();
System.out.println("--------------分割线-----------------");
//获取被代理类中的获取方法
dao.getById("123");
}
}
进行日志记录,方法为:doSave
执行保存方法【doSave】
事物提交
--------------分割线-----------------
进行日志记录,方法为:getById
执行根据ID查找对象方法【getById】

动态代理模式可以让我们在不改变原来代码结构的情况下,对原来的“真实方法”进行扩展、增强其功能,并且可以达到控制被代理对象的行为。

动态代理模式运用的知识点就是Java的反射机制,对于上面的代码有些地方我也不是很理解,要想彻底搞懂还有很长的路要走。

https://blog.csdn.net/mlc1218559742/article/details/52767156

Java反射机制在代理模式中的使用的更多相关文章

  1. Java反射机制在工厂模式中的应用

    在本篇文章中就不详细介绍工厂模式,主要介绍一下反射在工厂模式中的使用,让读者对反射机制带来的好处有更深的认识. 首先看一下简单工厂模式 简单工厂模式(simple factory)是类的创建模式,又叫 ...

  2. Java反射机制动态代理

    1.什么事反射机制动态代理 在一段代码的前后动态执行其他操作,比如有一个方法是往数据库添加一个记录,我们可以通过动态代理,在操作数据库方法的前和后添加代码执行打开数据库连接和关闭数据库连接. 2.演示 ...

  3. Java反射机制与工厂模式

    工厂模式属于创建型模式,它提供了一种创建对象的最佳方式. 它的特点是:客户端的程序类不直接牵扯到对象的实例化管理,只与接口发生关联,通过工厂类获取指定接口的实例化对象. 简单工厂模式如下: inter ...

  4. Java反射机制在Spring IOC中的应用

    反射的定义: 反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作.例如它允许一个java的类获取它所有的成员变量和方法并且显示出来. 反射机制的 ...

  5. java中的反射机制在Android开发中的用处

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反 ...

  6. Java反射机制(带应用)

    1.Java的反射机制:        Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态 ...

  7. Java 基础之详解 Java 反射机制

    一.什么是 Java 的反射机制?   反射(Reflection)是Java的高级特性之一,是框架实现的基础,定义:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法: ...

  8. java基础知识(十一)java反射机制(下)

    1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...

  9. Java反射与动态代理

    Java反射机制可以动态地获取类的结构,动态地调用对象的方法,是java语言一个动态化的机制.java动态代理可以在不改变被调用对象源码的前提下,在被调用方法前后增加自己的操作,极大地降低了模块之间的 ...

随机推荐

  1. 配置文件格式用哪个?文件夹+纯文本文件,XML,SQLite

    稍具规模的软件都会须要一个配置文件来支持软件的执行.眼下常见的配置文件格式有纯文本.XML.SQLite.自己定义二进制格式,怎样进行选择呢? 1 纯文本--永远不会失效的文件格式 文本化是传统Uni ...

  2. Discuz常见小问题-如何快速清除帖子

    看别人发的垃圾帖,然后鼠标移到用户名上面,在弹出菜单中点击禁止用户   设置禁止访问-全选所有,删除   然后短期内无法看到效果,帖子还在,你点进去会报错说指定的主题不存在   过三十分钟再刷新页面, ...

  3. 获取ArcGIS安装路径

    在要素类进行符号化时,使用axSymbologyControl需要安装路径下的Style文件路径,在AE9.3+VS2008中是这样的: Microsoft.Win32.RegistryKey reg ...

  4. 嵌入式 如何定位死循环或高CPU使用率(linux)

    如何定位死循环或高CPU使用率(linux)  确定是CPU过高 使用top观察是否存在CPU使用率过高现象 找出线程 对CPU使用率过高的进程的所有线程进行排序 ps H -e -o pid,tid ...

  5. 双硬盘Win7装Ubuntu 12.04经验并解决无线网络不能使用问题

    RFKill Many computer systems contain radio transmitters, including Wi-Fi, Bluetooth, and 3G devices. ...

  6. Failed to initialize storage module: user 的解决方式

    网上提供了一种解决方法就是在session_start()前把session的存储方式改为files,即加入以下一句代码 if (ini_get('session.save_handler') !== ...

  7. QtGui.QProgressBar

    A progress bar is a widget that is used when we process lengthy tasks. It is animated so that the us ...

  8. TCP/IP 工具Ping

    TCP/IP 工具Ping 在网络中Ping 是一个十分好用的TCP/IP工具.它主要的功能是用来检测网络的连通情况和分析网络速度. C:\Users\gechong>ping /? 用法: p ...

  9. 一致Hash算法

    一致性哈希算法是分布式系统中经常使用的算法.比方,一个分布式的存储系统,要将数据存储到详细的节点上.假设採用普通的hash方法.将数据映射到详细的节点上,如key%N.key是数据的key.N是机器节 ...

  10. 【Excle数据透视】多列分别分类计数

    需求 今天碰到一个很特殊的需求,如下(分别对每一列的值去重并统计个数): 预期结果 实现方法 推荐使用第三种方案,因为不用写公式,比较简单! 方法一:使用countif函数 在单元格J2输入公式COU ...