大话 CGLIB 和 JDK 生成动态代理类的那点事

创建动态代理对象bean,并动态注入到spring容器中 使用过Mybatis的同学,应该都知道,我们只需要编写mybatis对应的接口和mapper XML文件即可,并不需要手动编写mapper接口的实现。这里mybatis就用到了JDK动态代理,并且将生成的接口代理对象动态注入到Spring容器中。 这里涉及到几个问题。也许有同学会有疑问,我们直接编写好类,加入@Component等注解不是可以注入了吗?或者在配置类(@Configuration)... 阅读详情
AOP 使用的设计模式就是代理模式,是对IOC设计的补充。为了扩展性,往往会加上反射,动态生成字节码,生成代理类。 
这里往往还会使用到DI,把代理的实现类通过依赖注入的方式,传给代理工厂。 
关于生成动态代理类的方式有两种:JDK和CGLIB。 CGLIB,是一个开源工具。spring 和hibernate已经广泛使用。 

关于AOP的概念解释网上有很多。 
附件的内容是关于JDK和CGLIB动态生成代理工厂的实例。 

JDK动态代理和CGLIB字节码生成的区别? 

JDK动态代理只能对实现了接口的类生成代理,而不能针对类 。

CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成final。

例子为

@Component("SalesEmployee")

public class SalesDepartEmployee implements employee {

......

}

ApplicationContext ctx = new ClassPathXmlApplicationContext("employee.xml");
employee p=(employee)ctx.getBean("SalesEmployee");


employee  是接口名字。

则程序可以通过proxy-target-class="true" 来指定CGLIB)或proxy-target-class="false" 来指定 JDK proxy。

但是如果代码是这样

SalesDepartEmployee p=(SalesDepartEmployee )ctx.getBean("SalesEmployee");

则只能用CGLIB来生成代理,否则如果JDK proxy,则会出现下面的运行错误:

  java.lang.ClassCastException: 
   com.sun.proxy.$Proxy13 cannot be cast to salesdepart.service.app.SalesDepartEmployee


CGLIB生成代码
Java代码  收藏代码
  1. public Object createProxyObject(Object obj) {  
  2.     this.targetObject = obj;  
  3.     Enhancer enhancer = new Enhancer();  
  4.     enhancer.setSuperclass(obj.getClass());  
  5.     enhancer.setCallback(this);  
  6.     Object proxyObj = enhancer.create();  
  7.     return proxyObj;// 返回代理对象,返回的对象其实就是一个封装了“实现类”的代理类,是实现类的实例。  
  8. }  


JDK生成代码

Java代码  收藏代码
  1. public Object newProxy(Object targetObject) {// 将目标对象传入进行代理  
  2.     this.targetObject = targetObject;  
  3.     return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),  
  4.             targetObject.getClass().getInterfaces(), this);// 返回代理对象  
  5. }  

看上面的代码。在动太生成代理类时,传递的是实现类所所实现的接口argetObject.getClass().getInterfaces()。JDK只能对于接口进行做代理。如果换成类的话,则会抛java.lang.ClassCastException异常。 

下面就来一段代码说明下:

(Spring's configuration file,这里强行使用JDK proxy,见红字配置项)


emploee.xml 

--------------------------------------------------------------

<?xml version="1.0" encoding="GBK"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<!-- 指定自动搜索Bean组件、自动搜索切面类 -->
<context:component-scan base-package="salesdepart.service.app">
<context:include-filter type="annotation"
expression="org.aspectj.lang.annotation.Aspect"/>
</context:component-scan>
<!-- 启动@AspectJ支持 -->
<aop:aspectj-autoproxy proxy-target-class="false"/>
<context:annotation-config />
</beans>


employee .java

------------------------------------

package salesdepart.service.app;
public interface employee {
 public void displayInfo();
}


SalesDepartEmployee.java

----------------------------------

@Component("SalesEmployee")

public class SalesDepartEmployee implements employee {
 //@Autowired默认按类型装配,@Resource默认按名称装配
private String name;
//默认按类型装配
@Autowired(required=true) 
private DummyDAO mydao;
public SalesDepartEmployee() {
System.out.println(" SalesDepartEmployee() called");
name=" default";
mydao=null;
}
@Override
public void displayInfo() {
 System.out.println("displayInfo() called: this is Sales depart' employee "+name);
}

/**
* class specific method not provide in interface
*/
public void displayExtInfo() {
 System.out.println("displayExtInfo() called ");
}
public void setName(String name) {
this.name=name;
}
public String getName() {
return name;
}
}


BeanTest.java

---------------------------------------------

package salesdepart.service.app;
import org.springframework.context.*;
import org.springframework.context.support.*;
import java.util.*;
public class BeanTest { 
public static void main(String[] args) {
ApplicationContext ctx = new
ClassPathXmlApplicationContext("employee.xml");
SalesDepartEmployee p=(SalesDepartEmployee)ctx.getBean("SalesEmployee");

System.out.println("Hello: employee proxy class is "+p.getClass());
/**
 * this method can work well for JDK proxy and CGLIB proxy
 */
p.displayInfo();
 
/**
 * this method not provided in interface can work well for  CGLIB proxy ONLY.
 * If set  proxy-target-class="false", then see the below errors:
 *  java.lang.ClassCastException: 
 *  com.sun.proxy.$Proxy13 cannot be cast to salesdepart.service.app.SalesDepartEmployee

 */
p.displayExtInfo();
}
}


运行结果就是这样的

-----------------------

SalesDepartEmployee() called
Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy13 cannot be cast to salesdepart.service.app.SalesDepartEmployee
at salesdepart.service.app.BeanTest.main(BeanTest.java:10)

Arduino+esp8266+blinker物联网开发 文章目录blinker点灯一.简介二.开发环境的搭建1.arduino的安装2.添加esp8266开发板3. blinker库的导入4.驱动的安装4.手机端安装app三.开发第一个点灯程序1.添加设备2.载入示例3.代码部分4.代码讲解5.程序烧写四.总结 blinker点灯 一.简介 为了加深为物联网知识的认识,今天就教大家如何用手机app来控制我们的开发板。我们的开发环境是以arduino I... 阅读详情

相关推荐

【寄存器模型】二、前门访问与后门访问

1.后门访问可以更好的完成前门访问能够完成的事情:后门访问不消耗仿真时间,且消耗的运行时间也远小于前门访问的运行时间。 2.后门访问可以完成前门访问不能完成的事:对于某些特定的场景,如网络通信系统中的一些只读计数器,当要验证计数器进位归零的场景时,前门访问无法完成写寄存器操作,只能通过消耗仿真时间来使计数器到达特定的计数值。而后门访问可以直接对只读寄存器赋一个初值......

carrotbanana的博客 9656

Cglib和jdk动态代理的区别

Cglib和jdk动态代理的区别 Cglib和jdk动态代理的区别? 1、Jdk动态代理:利用拦截器(必须实现InvocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理 2、 Cglib动态代理:利用ASM框架,对代理对象类生成的class文件加载进来,通过修改其字节码生成子类来处理 什么时候用cglib什么时候用jdk动态代理? 1、目标对象生成了接口 默认用JDK动态代理 2、如果目标对象使用了接口,可以强制使用cglib 3、如果目标

小熊的博客 1461

西门子 S7-200 SMART 系列六:手把手教你配置S7-200 SMART Modbus RTU

最新发表:https://www.ics-pedia.com/%e8%a5%bf%e9%97%a8%e5%ad%90-s7-200-smart-%e7%b3%bb%e5%88%97%e5%85%ad%ef%bc%9a%e6%89%8b%e6%8a%8a%e6%89%8b%e6%95%99%e4%bd%a0%e9%85%8d%e7%bd%aes7-200-smart-modbus-rtu%e5%ae%9e%e4%be%8b/

John_09040211的博客 3279

Spring的两种代理JDK和CGLIB的区别浅谈

我的店铺 一、原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。 而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。 1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP...

钟渊博客 5万+

OTA(Over-The-Air)升级

OTA(Over-the-Air)是一种通过无线方式进行数据传输和更新的技术,通常用于电子设备(如智能手机、汽车、物联网设备等)的软件、固件或配置更新。OTA可以在设备与服务器之间进行远程传输,用户无需将设备接入电脑或进行有线操作。通过OTA,用户只需要通过Wi-Fi或移动网络连接,便能自动接收并安装最新的更新,而无需手动干预。OTA的优点是便捷和高效,能够确保设备随时保持最新状态,同时减少用户的操作负担。:如智能家居设备、路由器、汽车等硬件设备的固件更新。:确保设备上的应用保持最新版本。

weixin_50127894的博客 5058

超螺旋滑模控制(STA)

超螺旋滑模控制又称超扭滑模控制,可以说是二阶系统中最好用的滑模控制方法。

Lyajpunov的博客 1万+

JDK和CGLIB动态代理的区别

学习动态代理的区别

qq_59527118的博客 2万+

MuJoCo 关节角速度记录与可视化,监控机械臂运动状态

1. 手动计算关节速度,其中timestep为仿真步长。2. 使用data.qvel直接取得关节速度。

darcsdn 767

java-动态代理-jdk代理、cglib代理、生成字节码文件.

java-动态代理-jdk代理、cglib代理、生成字节码文件. 一、JDK动态代理和CGLIB字节码生成的区别?  * JDK动态代理只能对实现了接口的类生成代理,而不能针对类  * CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法    因为是继承,所以该类或方法最好不要声明成final  二、静态代理、动态代理区别? 静态代理:由程序员创建

草青工作室 的专栏 4002

MFC使用Websocket通讯介绍和实例(附完整源码)

踩坑点,下载了好几个boost版本编译,经常出问题,后来搜索了好久资料才发现如下评论:WebSocket++0.8.2 has been tested through Boost 1.72。WebSocketpp依赖于boost,因此在使用WebSocketpp前需要编译Boost;所以我们直接下载Boost 1.72的windows版的进行安装,安装完成还需要编译;WebSocketpp也叫WebSocket++;服务编译好之后,使用。

weixin_42530684的博客 1171

PPF函数可视化生产可能性边界线(R语言)

假设产品A的生产函数为A = 2 * R1 + R2,产品B的生产函数为B = R1 + 2 * R2,其中A和B分别表示产品A和产品B的产量,R1和R2表示资源1和资源2的分配数量。首先,让我们定义两种产品:产品A和产品B,它们的生产分别需要不同的资源和技术。现在我们已经计算了每种分配比例下的产品A和产品B的产量,接下来我们可以绘制生产可能性边界线。运行完整的代码后,我们将得到一个图形,显示了生产可能性边界线,该线代表经济体在给定资源和技术条件下所能生产的所有产品组合。

2301_79326559的博客 874

大话java之JDK动态代理和CGLIB动态代理

上一篇讲到了java的动态代理和JDK动态代理的使用和原理。这一篇要讲讲cglib代理,和jdk代理使用上的一个重要区别是jdk代理必须是以接口为委托类。那么在委托类不是接口的情况下,就可以使用gclib动态代理了。 gclib的实现代码如下: 1)委托类public class TestImplement { @Override public void business() {

I am a coder 794

斯坦福大学3D点云模型下载

本文整理了斯坦福大学10个经典的点云(pcd)及其模型(ply),方便日后使用,欢迎免费下载!

孙悟空 7733

java动态代理

前段时间去学习了一下RPC原理,其中提到了动态代理。特意去学习了一下,为了防止以后忘记,写下这篇博客做个记录,有不对的地方欢迎指正。 java中的常见的动态代理如Spring AOP。关于动态代理首先需要了解代理模式,根据代理类的创建时间又可以分为静态代理和动态代理。 1、代理模式 代理模式是常见的设计模式之一,Java我们通常通过new一个对象然后调用其对应的方法来访问我们需要的服务。代理模式则...

飞!!!的博客 5万+

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

代理模式(JDK,CGLIB动态代理,AOP切面编程)

/ 定义接口// 实现类(目标类)@OverrideSystem.out.println("RealService 正在执行工作...");

tiantiantbtb的博客 1300

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Java代理模式(静态代理、JDK动态代理、CGLIB)

代理模式是常见的设计模式之一,Java我们通常通过new一个对象然后调用其对应的方法来访问我们需要的服务。代理模式则是通过创建代理类(proxy)的方式来访问服务,代理类通常会持有一个委托类对象,代理类不会自己实现真正服务,而是通过调用委托类对象的相关方法,来提供服务,所以其实我们调用的还是委托类的服务,但是中间隔了一个代理类。这么做是有好处的,我们可以在访问服务之前或者之后加一下我们需要的操作。例如Spring的面向切面编程,我们可以在切入点之前执行一些操作,切入点之后执行一些操作。这个切入点就是一个个方

日常技术分享 236

JDK动态代理和cglib动态代理(AOP的底层实现原理)

一、代理设计模式 代理类和委托类具有相同的接口。代理类的对象本身并不真正实现服务,而是通过委托类的对象的相关方法来提供特定的服务。 二、静态代理 见《大话设计模式》第7章 缺点: 一个代理类只能应用于一个接口的实现类,如果有多个接口的话就要定义很多实现类和代理类才行。而且,如果代理类对业务方法的预处理、调用后操作都是一样的(比如:调用前输出提示、调用后自动关闭连接),则多个代理类就会有很...

g1607058603的专栏 1053

设计模式之代理模式 静态代理和动态代理

welcome to my blog 代理模式的定义 《大话设计模式》中对于代理模式的描述: 代理模式为其他对象提供一种代理以控制对这个对象的访问. 通俗点说就是, 通过一个中间对象访问目标对象. 代理模式在生活中的体现 租房时需要看房, 往往是中介的人带着咱们去看房, 并不是直接由房东带着去看房. 注意到房子是属于房东的属性, 但是我们并没有通过房东访问这个属性, 而是通过中介访问这个属性, 这...

littlehaes的博客 717

大话java之JDK动态代理

上一篇讲到到java的代理模式以及java的静态代理的实现方式。静态代理的问题在于需要为每个委托类建立一个代理类,这样不仅耗费大量的精力,也不利于项目的解耦和维护。本篇就要讲讲java的动态代理,动态代理在spring等框架中十分重要,它不仅保留代理模式的优点,也更好地解耦项目,对于代码的复用和维护都是更有优势。 1.先举个动态代理的简单例子:1)委托类接口//委托类接口 public inter

I am a coder 1872

大话Java动态代理机制

转自:微点阅读https://www.weidianyuedu.com retrofit是一个解耦性非常高的网络请求框架,最近在研究的时候发现了动态代理这个非常强大且实用的技术,这篇文章将作为retrofit的前置知识,让大家认识:动态代理有哪些应用场景,什么是动态代理,怎样使用,它的局限性在什么地方? #动态代理的应用场景 1. AOP—面向切面编程,程序解耦 简言之当你想要对一些类的内部的一些方法,在执行前和执行后做一些共同的的操作,而在方法中执行个性化操作的时候--用动态代理。在业务量庞大..

ysds20211402的博客 166

从兄弟到父子:CGLIB动态代理的玩法

前言:本文为《Java帝国之动态代理》的姊妹篇, 讲述动态代理的另外一种实现即CGLib的设计过程。 当IO大臣绞尽脑汁地在府中设计Java动态代理的时候,他并不知道,在帝国的一个小小的部落,一个年轻的小伙子正在为同样的问题而苦恼。 师傅刚刚给小伙子下达了任务:在运行时对一个类进行扩展, 例如有个类叫HelloWorld,要在运行时给他加点日志输出的代码。 师傅特别告诉年轻人:“大胖, ...

llllllxj的博客 626

动态代理之继承(兄弟)

前言:本文为《Java帝国之动态代理》的姊妹篇, 讲述动态代理的另外一种实现即CGLib的设计过程。 当IO大臣绞尽脑汁地在府中设计Java动态代理的时候,他并不知道,在帝国的一个小小的部落,一个年轻的小伙子正在为同样的问题而苦恼。 师傅刚刚给小伙子下达了任务:在运行时对一个类进行扩展, 例如有个类叫HelloWorld,要在运行时给他加点日志输出的代码。 师傅特别告诉年轻人:“大胖, 你要注...

weixin_43755216的博客 354

SpringAop底层原理 Java动态代理思想

java动态代理实现与原理详细分析 关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式–代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理。 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托...

evanYang的博客 378

大话代理模式(静态代理and动态代理)超级形象好理解!!!

代理模式是一种结构型设计模式,其目的是在访问对象时引入一个代理对象,这个代理对象可以控制对原始对象的访问,并且可以在访问前后执行一些额外的操作。代理模式通常用于在不改变原始对象的情况下,为其提供额外的功能,或者对其访问进行控制,以满足特定需求。比如:当拍电影的时候,演员寻找替身演员,就是一个代理模式。对于观众来说,只是看到了电影中的危险动作的完成,不会区分演员和替身演员。//该接口为目标对象和代理对象都需要实现的接口//客户端只是面向接口编程public interface 表演接口{

weixin_43836337的博客 646

代理模式学习笔记

原文链接:https://blog.youkuaiyun.com/xiaofeng10330111/article/details/105633821 关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理。 一、代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的

学习笔记 818

java动态代理源码简析

动态代理源码解析

QG 330

大话设计模式之代理模式

今天我们来总结一下一个常见的设计模式---代理设计模式。首先我们看一下代理模式的UML图: 然后呢我们根据UML图把代码写一下: public interface Subject{ public void Request(); } public class RealSubject impl...

xiaomin的博客 292
上一篇: Cglib 与 JDK动态代理的运行性能比较: JDK7 代理远优于cglib
下一篇: Spring4.x 不再支持JpaTemplate和JpaDapSupport类了
大树叶
博客等级 码龄12年 1171粉丝 664原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值