需求:增强未知方法的代码

简单方案:继承或者聚合

  1. 继承,调用方法前后加增强逻辑

  2. 聚合 - 静态代理

    1. 持有被代理类对象 或者接口

    2. 可通过嵌套实现代理的组合 和 装饰器模式很像

高级方案

  • 代理所有的类,不只是某一类的接口,静态的聚合方式成员属性是具体的
JDK 动态代理
package club.interview.design_pattern.chapt6_proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; /**
* @author QuCheng on 2020/6/15.
*/
public interface Vegetable { void growUp(); class Cabbage implements Vegetable { @Override
public void growUp() {
System.out.println("卷心菜慢慢长大");
}
} class LogProxy implements InvocationHandler { Object o; public LogProxy(Object o) {
this.o = o;
} public static Object getProxy(Object object) {
System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
return Proxy.newProxyInstance(object.getClass().getClassLoader(),
object.getClass().getInterfaces(), new LogProxy(object));
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("good goods study");
Object invoke = method.invoke(o, args);
System.out.println("day day up");
return invoke;
} public static void main(String[] args) {
Vegetable v = (Vegetable) LogProxy.getProxy(new Cabbage());
v.growUp();
}
} } 
  • proxy源码解读

    • 实际产生的对象是$Proxy0.class的对象,继承proxy,实现目标接口方法
    • 执行目标接口时实际调用super也就是proxy的InvokationHandler的invoke对象
  • 生成代理源码解读Proxy.newInstance(...)
    • 跟进去会发现底层是利用asm动态生成二进制文件$Proxy0.class
Cglib
package club.interview.design_pattern.chapt6_proxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
* @author QuCheng on 2020/6/15.
*/
public class CabbageCglib {

public void growUp() {
System.out.println("卷心菜慢慢长大");
}

static class LogProxyCglib implements MethodInterceptor {

@SuppressWarnings("unchecked")
static <T> T getProxy(T o) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(o.getClass());
enhancer.setCallback(new LogProxyCglib());
return (T) enhancer.create();
}

@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("good good study");
// invokeSuper not invoke
Object invoke = methodProxy.invokeSuper(o, objects);
System.out.println("day day up");
return invoke;
}
}

public static void main(String[] args) {

CabbageCglib cabbageCglib = LogProxyCglib.getProxy(new CabbageCglib());
cabbageCglib.growUp();
}
}
两种动态代理对比
  • jdk

    • 优点:jdk原生,可代理有接口实现的类

    • 缺点:代理类必须实现接口

  • cglib

    • 优点:

      • 被代理类无需实现接口

      • 实现简单,无需聚合

    • 缺点:因为是采用继承,被代理类不能被final修饰

【DP-动态代理】JDK&Cglib的更多相关文章

  1. Spring -07 -AOP [面向切面编程] - 使用注解@+ AspectJ 方式实现环绕/前/后等通知 -超简洁 --静态代理/动态代理{JDK/cglib}

    1.spring 不会自动去寻找注解,必须告诉 spring 哪些包下的类中可能有注解;使用注解来取代配置文件.1.1 引入xmlns:context ,指定扫描范围 <context:comp ...

  2. AOP学习心得&jdk动态代理与cglib比较

    什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...

  3. Spring AOP详解 、 JDK动态代理、CGLib动态代理

    AOP是Aspect Oriented Programing的简称,面向切面编程.AOP适合于那些具有横切逻辑的应用:如性能监测,访问控制,事务管理以及日志记录.AOP将这些分散在各个业务逻辑中的代码 ...

  4. 【转载】Spring AOP详解 、 JDK动态代理、CGLib动态代理

    Spring AOP详解 . JDK动态代理.CGLib动态代理  原文地址:https://www.cnblogs.com/kukudelaomao/p/5897893.html AOP是Aspec ...

  5. 017 Java中的静态代理、JDK动态代理、cglib动态代理

    一.静态代理 代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理. 静态代理由业务实现类.业务代理类两部分组成.业务实现类负责实现主要的业务方法,业 ...

  6. JDK动态代理与CGLib动态代理相关问题

    导读: 1.JDK动态代理原理是什么?为什么不支持类的代理? 2.JDK动态代理实例 3.CGLib代理原理是什么? 4.CGLib代理实例 5.JDK动态代理与CGLib代理的区别是什么? 6.总结 ...

  7. Java之代理(jdk静态代理,jdk动态代理,cglib动态代理,aop,aspectj)

    一.概念 代理是什么呢?举个例子,一个公司是卖摄像头的,但公司不直接跟用户打交道,而是通过代理商跟用户打交道.如果:公司接口中有一个卖产品的方法,那么公司需要实现这个方法,而代理商也必须实现这个方法. ...

  8. 动态代理 JDK动态代理 CGLIB代理

    代理模式:代理类和被代理类实现共同的接口(或继承),代理类中存有指向被代理类的索引,实际执行时通过调用代理类的方法.实际执行的是被代理类的方法. 而AOP,是通过动态代理实现的. 一.简单来说: JD ...

  9. 动态代理jdk和cglib的区别

    学习来源贴:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类, ...

  10. JDK动态代理、CGLib动态代理

    JDK动态代理源码 一.public static Object newProxyInstance ——> 调用下面这个方法二.Class<?> cl = getProxyClass ...

随机推荐

  1. Bank5

    Account: package banking5; //账户 public class Account { protected double balance; public Account(doub ...

  2. 关于hexo中plugins博客配置对无法生成index.html文件的影响

    用hexo搭建的博客网站在访问时出现403错误,经调查后发现是public文件夹下的index.html文件丢失. 在csdn上搜了一下发现大家都是查看是否有一下hexo的插件未安装,将未安装插件安装 ...

  3. Redis详解(十一)------ 过期删除策略和内存淘汰策略

    在介绍这篇文章之前,我们先来看如下几个问题: ①.如何设置Redis键的过期时间? ②.设置完一个键的过期时间后,到了这个时间,这个键还能获取到么?假如获取不到那这个键还占据着内存吗? ③.如何设置R ...

  4. Rocket - tilelink - WidthWidget

    https://mp.weixin.qq.com/s/pmJcsRMviJZjMwlwYw6OgA   简单介绍WidthWidget的实现.   ​​   1. 基本介绍   用于设定与上游节点连接 ...

  5. HashMap1.7和1.8,红黑树原理!

    jdk 1.7 概述 HashMap基于Map接口实现,元素以键值对的方式存储,并允许使用null键和null值,但只能有一个键作为null,因为key不允许重复,另外HashMap不能保证放入元素的 ...

  6. Java实现 蓝桥杯VIP 算法训练 比赛安排

    问题描述 设有有2 n(n<=6)个球队进行单循环比赛,计划在2 n – 1天内完成,每个队每天进行一场比赛.设计一个比赛的安排,使在2 n – 1天内每个队都与不同的对手比赛. 输入格式 输入 ...

  7. Java实现第十届蓝桥杯等差数列

    试题 I: 等差数列 时间限制: 1.0s 内存限制: 512.0MB 本题总分:25 分 [问题描述] 数学老师给小明出了一道等差数列求和的题目.但是粗心的小明忘记了一 部分的数列,只记得其中 N ...

  8. 二叉树的层次序列化和反序列化-----stringstream

    string serialize(TreeNode* root) {//层序便利,将空的子节点也放入到字符串 ostringstream out; queue<TreeNode*> q; ...

  9. tensorflow2.0学习笔记第二章第三节

    2.3激活函数sigmoid函数 f(x)= 1/(1 + e^-x)tf.nn.sigmoid(x)特点:(1)求导后的数值在0-0.25之间,链式相乘之后容易使得值趋近于0,形成梯度消失 (2)输 ...

  10. Flutter 中 GestureDetector 的使用误区

    在实际开发中,我们通常需要实现某个组件的更多点击事件.比如:原生的RaisedButton组件是无法响应诸如拖拽或是按下.抬起等细化的动作,它只有一个onPressed()方法来表示.当我们想实现这些 ...