代理设计模式
代理设计模式的基本形式
代理设计模式的核心思路,一个接口两个子类,一个子类完成核心业务操作,另一个完成与核心业务有关的辅助性操作。例如,编写一个简单的设计模式。
package com.hbsi.test;
interface Food{
public void eat();
}
class ProxyFood implements Food{
private Food food;
public ProxyFood(Food food) {
this.food = food;
}
public void after() {
System.out.println("饭后");
}
public void before() {
System.out.println("饭前");
}
@Override
public void eat() {
this.after();
this.food.eat();//调用RealFood中的eat方法
this.before();
}
}
class RealFood implements Food{
@Override
public void eat() {
System.out.println("吃饭 ,,,,,RealFood");
}
}
public class ProxyDemo {
public static void main(String[] args) {
Food f = new ProxyFood(new RealFood());
f.eat();
}
}

 在什么情况下代理设计模式可能会被使用?最常用的形式就是在系统日志上进行,

 
动态代理类
传统的代理模式都是一个接口两个子类,一个是真实主题类,另一个是代理类,这样就导致了,一个代理类只能为一个接口服务,所以在java中提供了动态代理的支持。
如果要实现动态代理类,必须采用InvocationHandle接口处理。
此接口中定义了一个invoke方法:
Object invoke​(Object proxy, Method method, Object[] args) throws Throwable
处理代理实例上的方法调用并返回结果。
在这个invoke方法里面接受的参数如下,
1. proxy:代理的对象,
2. method:表示真实主题要调用的执行方法;
3. args:调用方法时所传递的参数
而在invoke'方法里面会返回一个Object的数据,这个数据就是调用方法时,返回的结果
但是所哟的真实主体累,都需要返回一个代理类对象,而这个代理类对象都由Proxy类完成,在Proxy类中的一个操作方法:
返回指定接口的代理实例,该代理实例将方法调用分派给指定的调用处理程序。
在此方法中有以下参数:
loader :返回目标对象的类加载器;读取要代理类的代码,重新实例化一个新的
interfaces:返回一个类实现的所有接口
h:InvocationHandler 接口对象,完成真正的代理操作。
代码示例:建立一个动态代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyProxyd implements InvocationHandler{
private Object target;//要代理的对象信息
public Object bind(Object target) {
this.target = target;//赋值
//返回与当前传入对象结构相同的代理类对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces() , this);
}
@Override//参数说明:代理的对象。表示真实主体类要执行的方法。方法需要的参数
public Object invoke(Object proxy, Method method, Object[] arg) throws Throwable {
this.log();
Object invoke = method.invoke(this.target, arg);//调用真实类的方法
this.commit();
return invoke;
}
private void log() {
System.out.println("执行记录日志方法");
}
private void commit() {
System.out.println("事务提交");
}
public static void main(String[] args) {
Food f = (Food) new MyProxyd().bind(new RealFood());
f.eat();
}
}
public class RealFood implements Food{
@Override
public void eat() {
System.out.println("吃饭 ,,,,,RealFood");
}
}

 

CGLIB代理模式、
从标准的代理设计模式来讲,一定要有借口,而且通过之前的动态代理也可以发现,如果想要去的代理类对象,就必须传入接口。
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces() , this);
使用Proxy必须传入所有接口,否则代理不能使用。为了解决java动态代理的必须需要接口的弊端,CGLIB可以解决此问题。
cglib包中需要使用以下几个类:
1. net.sf.cglib.proxy.Enhancer,相当于 Proxy 功能,返回代理对象
2. net.sf.cglib.proxy.MethodInterceptor接口:处理一个代理操作的接口
3. net.sf.cglib.proxy.MethodProxy:代替之前的Method类的功能
代码范例:基于类实现的动态代理设计模式
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
class PrintMes {
public void print() {
System.out.println("吃饭 ,,,,,");
}
}
public class CGLIBProxy {
public static void main(String[] args) {
PrintMes mes = new PrintMes();//
Enhancer enhancer = new Enhancer();//代理类对象
enhancer.setSuperclass(mes.getClass());//为代理类设置一个父类,自我理解就是做关联
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] objs, MethodProxy proxy) throws Throwable {
System.out.println("饭前洗手");
return method.invoke(mes, args);
}
});
PrintMes create = (PrintMes) enhancer.create();//返回代理对象
create.print();//调用
}
}

java--动态代理设计模式,CGLIB实现的动态代理设计模式的更多相关文章

  1. 性能优于JDK代理,CGLib如何实现动态代理

    按照代理的创建时期,代理类可以分为两种. 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了. 动态代理:在程序运行时,运用反射机制动态创建 ...

  2. java提供类与cglib包实现动态代理

    终于有点空余时间,决定把之前学习的知识点整理一下,备以后复习. 动态代理有三角色:抽象角色,代理角色,真是角色. 第一个记录下java提供的动态代理.即使用Proxy类和InvocationHande ...

  3. java动态代理--proxy&cglib

    大纲 代理 proxy cglib 小结 一.代理 为什么要用代理?其实就是希望不修改对象的情况下,增强对象. 静态代理: 静态代理模式,需要代理类和目标类实现同一接口,代理类的方法调用目标类的方法, ...

  4. 学习CGLIB与JDK动态代理的区别

    动态代理 代理模式是Java中常见的一种模式.代理又分为静态代理和动态代理.静态代理就是显式指定的代理,静态代理的优点是由程序员自行指定代理类并进行编译和运行,缺点是一个代理类只能对一个接口的实现类进 ...

  5. CGLib方式对接口实现代理

    JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了.CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采 ...

  6. java设计模式(一)动态代理模式,JDK与CGLIB分析

    -本想着这个知识点放到Spring Aop说说可能更合适一点,但因为上一篇有所提到就简单分析下,不足之处请多多评论留言,相互学习,有所提高才是关键! 什么是代理模式: 记得有本24种设计模式的书讲到代 ...

  7. Java动态代理与Cglib库

    JDK动态代理 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在 ...

  8. Java代理(jdk静态代理、动态代理和cglib动态代理)

    一.代理是Java常用的设计模式,代理类通过调用被代理类的相关方法,并对相关方法进行增强.加入一些非业务性代码,比如事务.日志.报警发邮件等操作. 二.jdk静态代理 1.业务接口 /** * 业务接 ...

  9. [z]Java代理(jdk静态代理、动态代理和cglib动态代理)

    一.代理是Java常用的设计模式,代理类通过调用被代理类的相关方法,并对相关方法进行增强.加入一些非业务性代码,比如事务.日志.报警发邮件等操作. 二.jdk静态代理 1.业务接口 1 2 3 4 5 ...

  10. 代理模式 & Java原生动态代理技术 & CGLib动态代理技术

    第一部分.代理模式  代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常 ...

随机推荐

  1. django 自定义 密码加密方式 及自定义验证方式

    在django1.6中,默认的加密方式是pbkdf_sha256,具体算法不表,一直以来用django的自带用户验证都十分顺手,但如果需要修改默认加密方式为md5,具体方法为: 在settings.p ...

  2. 基于grafana+prometheus构建Flink监控

    先上一个架构图 Flink App : 通过report 将数据发出去 Pushgateway :  Prometheus 生态中一个重要工具 Prometheus :  一套开源的系统监控报警框架 ...

  3. vs2010 出错:error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏(转)

    “LNK1123:转换到 COFF期间失败:文件无效或损坏”的解决方法 一.错误描述 之前写的程序隔段时间使用VS2010再次运行时出现如下错误: LINK fatal error LNK1123转换 ...

  4. MVC ViewBag和ViewData的使用

    ViewBag public ActionResult About() { ViewBag.Message = "Your application description page.&quo ...

  5. TroubleShooting经验总结

    1.WinDbg是微软开发的免费源代码级的调试工具.WinDbg可以用于Kernel模式调试和用户模式调试,还可以调试Dump文件.WinDbg对于dump文件的调试可以通过菜单设置Symbol Fi ...

  6. expect 实现自动交互脚本

    1. 说明 在编写脚本时,可能会遇到需要在另一台主机上执行一个命令,或者在本机拷贝另一台主机内的一个文件.如果两台主机之间没有做互信,就会牵扯到用户输入密码的交互过程,这对编写自动脚本来说, 就行不通 ...

  7. MySQL插入大批量数据时报错“The total number of locks exceeds the lock table size”的解决办法

    事情的原因是:我执行了一个load into语句的SQL将一个很大的文件导入到我的MySQL数据库中,执行了一段时间后报错"The total number of locks exceeds ...

  8. 【TensorRT】自定义网络层的实现custom layers

    参考 1. Extending TensorRT With Custom Layers; 2. TensorRT Samples: MNIST(Plugin, add a custom layer); ...

  9. windows修改系统登录密码后,出现SQLserver服务无法启动,启动报错17051

    windows修改系统登录密码后,出现SQLserver服务无法启动,启动报错17051具体报错如下: 根据错误提示,去到windows的事件查看器.在win10上,右击左下角的菜单图标:然后依次点击 ...

  10. Meerkat软件

    一.准备工作 meerkat 0.189版本和以前的版本相比,支持bwa mem 输出的bam文件,还支持全外显子数据count SV. meerkat原理 1.1 需要准备的软件 unix/Linu ...