动态代理

JDK动态代理VS CgLib

試著忘記壹切 提交于 2020-05-07 20:24:32
业务场景 描述:每个旅客乘坐火车时,在上车、下车之前需要检票。站在乘客的角度,这个过程可以看做一件事:检票坐车检票;也可以看做两件事:检票,坐车;站在检票员的角度,那就是一件事,检票。 如果我们用代码实现,可能是这样的过程: checkTicket(); takingTrain(); checkTicket(); 如果有一天,车站变成刷身份证进站了,我们就得回去改代码了... 下面我们将这个过程分开,用代理来解决坐车意外的问题: 业务逻辑:坐火车 额外需要:检票/刷卡 具体实现 JDK动态代理,主要类、接口:Proxy, InvocationHandle,JDK动态代理特点只能对接口进行代理 所以需要一个业务逻辑接口:TakingTrain; package com.spring.mybean; public interface TakingTrain { public void takeTrain(String name); } 实现类:TakingTrainImpl------>要被代理的目标类,实现TakingTrain接口 package com.spring.mybean.imp; import com.spring.mybean.TakingTrain; public class TakingTrainImpl implements TakingTrain {

使用 Java AOP API 完成动态代理的一些注意事项

此生再无相见时 提交于 2020-04-07 02:08:27
###代码示例 Java原生API中,动态代理常用的API有两个:InvocationHandler接口和Proxy类 首先上代码StaffLoggerAspect.java public class StaffLoggerAspect implements InvocationHandler { Object target; public Object getObject(Object object) { target = object; return Proxy.newProxyInstance(Staff.class.getClassLoader(), Staff.class.getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(proxy.getClass().getName()); return method.invoke(target, args); } } Main类的main方法 public static void main(String[] args) { StaffLoggerAspect aspect = new

你必须会的 JDK 动态代理和 CGLIB 动态代理

邮差的信 提交于 2020-04-06 15:52:30
我们在阅读一些 Java 框架的源码时,基本上常会看到使用动态代理机制,它可以无感的对既有代码进行方法的增强,使得代码拥有更好的拓展性。 通过从静态代理、JDK 动态代理、CGLIB 动态代理来进行本文的分析。 静态代理 静态代理就是在程序运行之前,代理类字节码 .class 就已编译好,通常一个静态代理类也只代理一个目标类,代理类和目标类都实现相同的接口。 接下来就先通过 demo 进行分析什么是静态代理,当前创建一个 Animal 接口,里面包含 call 函数。 package top.ytao.demo.proxy; /** * Created by YangTao */ public interface Animal { void call(); } 创建目标类 Cat,同时实现 Animal 接口,下面是 Cat 发出叫声的实现。 package top.ytao.demo.proxy; /** * Created by YangTao */ public class Cat implements Animal { @Override public void call() { System.out.println("喵喵喵 ~"); } } 由于 Cat 叫之前是因为肚子饿了,所以我们需要在目标对象方法 Cat#call 之前说明是饥饿

动态代理的实际应用

柔情痞子 提交于 2020-04-06 10:53:15
原文链接 前言 最近在用 Python 的 SQLAlchemy 库时(一个类似于 Hibernate 的 ORM 框架),发现它的 Events 事件还挺好用。 简单说就是当某张表的数据发生变化(曾、删、改)时会有一个事件回调,这样一些埋点之类的需求都可以实现在这里,同时和业务代码完全解耦,维护起来也很方便。 例如当订单状态发生变化需要发异步通知这样的需求也可以利用这个实现。 根据我之前使用 Mybatis 的经验,好像没怎么注意有这个功能,查阅了下发现 Hibernate 是支持的,只是我用得也少,所以也没怎么在意。 > 逐渐偏离主题。。。 说这些的主要原因是我打算为之前写的 cicada (轻量的 http 框架)加一个数据库操作包,也实现类似的功能。 示例 最终的使用效果如下: > 第一版本还比较粗糙,但功能都具备。 第一步:需要实现一个初始化接口,该接口会在应用初始化的时候执行。 紧接着我们需要定义一个 Model : @Data @OriginName("user") @ToString public class User extends Model { @PrimaryId private Integer id ; private String name ; private String password ; @FieldName(value = "city_id")

代理

瘦欲@ 提交于 2020-04-06 02:17:46
动态代理 //接口类 public interface PersonBehavior { void talk () ; void jump () ; } //实现类(被代理类) public class DefaultPersonBehavior implements PersonBehavior { @Override public void talk () { System. out .println( "We can talk" ) ; } @Override public void jump () { System. out .println( "We can jump" ) ; } } public class PersonBehaviorHandler implements InvocationHandler { private Object target ; public PersonBehaviorHandler (Object target) { this . target = target ; } @Override public Object invoke (Object proxy , Method method , Object[] args) throws Throwable { System. out .println( "We can do

代理模式

十年热恋 提交于 2020-04-05 16:46:07
代理模式 (Proxy Pattern)是只为其他对象提供一种代理,以控制对这个对象的访问,属于结构行模式。 代理模式一般包含三种角色: 抽象主题角色:抽象主题类的主要职责是声明真实主题与代理的共同接口方法,该类可以是接口也可以说抽象类。 真实主题角色:该类被称为代理类,该类定义了代理所表示的真实对象,是负责执行系统真正逻辑业务对象。 代理主角色:也被称为代理类;其内部持有(真实主题角色)的引用,因此具备完全的对(真实主题角色)的代理权。客户端调用代理对象方法,同时也调用了代理类方法,但是会在代理类对象前后增加一些处理代码。 优点: 1、代理模式能将代理对象与真实被调用目标对象分离。 2、在一定程度上降低了系统的耦合性,扩展性好。 3、可以起到保护目标对象的作用。 4、可以增强目标对象的功能。 缺点: 1、代理模式会造成系统设计中类的数量增加。 2、在客户端和目标对象中增加一个代理对象,会导致请求处理速度变慢。 3、增加了系统的复杂度。 应用场景:系统日志、事物代理、springAopd等。 静态代理: 静态代理只能通过手动完成代理操作,如果被代理类增加了新的方法,代理类需同步增加,违背开闭原则。 代码示例: (静态代理只负责自己代理的;如下只能代理售票,如新增一个售卖其他的类无法代理) //售票接口(抽象主题角色) public interface ITicketSales {

Spring Boot实践——AOP实现

随声附和 提交于 2020-04-01 07:56:45
Spring AOP 介绍   AOP的介绍可以查看 Spring Boot实践——AOP实现   与AspectJ的静态代理不同,Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。   Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是 InvocationHandler 接口和 Proxy 类。   如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,是利用asm开源包, 可以在运行时动态的生成某个类的子类 。注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为 final ,那么它是无法使用CGLIB做动态代理的。   这里有注意的几点如下: 从Spring 3.2以后不再将CGLIB放在项目的classpath下,而是将CGLIB类打包放在spring-core下面的org.springframework中

静态代理&动态代理

大兔子大兔子 提交于 2020-04-01 07:55:56
原文地址:http://blog.csdn.net/partner4java/article/details/7048879 静态AOP和动态AOP。 静态代理: 代理对象与被代理对象必须实现同一个接口。 demo: package cn.partner4java.proxy.staticproxy; /** * 静态代理,统一接口 * @author partner4java * */ public interface IHello { /** * 可以带来的统一方法 * @param name */ public void hello(String name); } package cn.partner4java.proxy.staticproxy; /** * 被代理的对象,需要借助代理对象加入日志 * @author partner4java * */ public class HelloSpeaker implements IHello { public void hello(String name) { System.out.println( "Hello " + name); } } package cn.partner4java.proxy.staticproxy; /** * 代理对象,给被代理对象添加日志 */ public class HelloProxy

Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)

我是研究僧i 提交于 2020-04-01 07:47:43
class文件简介及加载   Java编译器编译好Java文件之后,产生.class 文件在磁盘中。这种class文件是二进制文件,内容是只有JVM虚拟机能够识别的机器码。JVM虚拟机读取字节码文件,取出二进制数据,加载到内存中,解析.class 文件内的信息,生成对应的 Class对象: class字节码文件是根据JVM虚拟机规范中规定的字节码组织规则生成的、具体class文件是怎样组织类信息的,可以参考 此博文: 深入理解Java Class 文件格式系列。 或者是 Java虚拟机规范 。 下面通过一段代码演示手动加载 class文件字节码到系统内,转换成class对象,然后再实例化的过程: a. 定义一个 Programmer类: package samples; /** * 程序猿类 * @author louluan */ public class Programmer { public void code() { System.out.println("I'm a Programmer,Just Coding....."); } } b. 自定义一个类加载器: package samples; /** * 自定义一个类加载器,用于将字节码转换为class对象 * @author louluan */ public class MyClassLoader extends

JDK动态代理你所不知道的事情

百般思念 提交于 2020-03-31 10:29:30
先写一个动态代理实现 1.写接口类 2.写真实对象,真实对象实现上面的接口 3.写代理类,实现InvocationHandler接口,并重写invoke方法 输出结果如下 看b.work3()的输出,只有work3通过代理对象(proxy)调用,所以“加入些额外的功能” 在work3()方法里面的wor1()和work2调用,其实是通过this(代表真实对象)调用的。 this.wor1(),this.work2代表的是真实对象的调用 结论:只有代理对象调用的方法才会被代理增强新功能 真实对象调用的方法不会被代理增强新功能 扩展:spring中的事务,为什么再同一类中方法调用同一个类中的另外一个方法回失效? 如上图:insert方法中调用insert2(),无论insert2的事务隔离级别定义的是哪一种,insert2的事务都会失效, insert2只会被当作insert中的执行代码块 原因:spring的事务是通过AopProxy实现的,底层用的是jdk的动态代理,insert2()方法的调用是通过this,而不是代理类,所以增强功能失效 怎么解决呢?请看我的另一篇文章 来源: 51CTO 作者: qq5e5f48e3af387 链接: https://blog.51cto.com/14743302/2483044