java动态代理的实现原理
- 格式:docx
- 大小:14.88 KB
- 文档页数:2
目前整个开发社区对AOP(Aspect Oriented Programing)推崇备至,也涌现出大量支持AOP的优秀Framework,--Spring, JAC, Jboss AOP 等等。AOP似乎一时之间成了潮流。Java初学者不禁要发出感慨,OOP还没有学通呢,又来AOP。本文不是要在理论上具体阐述何为AOP, 为何要进行AOP . 要详细了解学习AOP可以到它老家去瞧瞧。这里只是意图通过一个简单的例子向初学者展示一下如何来进行AOP.
为了简单起见,例子没有没有使用任何第三方的AOP Framework, 而是利用Java语言本身自带的动态代理功能来实现AOP.
让我们先回到AOP本身,AOP主要应用于日志记录,性能统计,安全控制,事务处理等方面。它的主要意图就要将日志记录,性能统计,安全控制等等代码从商业逻辑代码中清楚的划分出来,我们可以把这些行为一个一个单独看作系统所要解决的问题,就是所谓的面向问题的编程(不知将AOP译作面向问题的编程是否欠妥)。通过对这些行为的分离,我们希望可以将它们独立地配置到商业方法中,而要改变这些行为也不需要影响到商业方法代码。
假设系统由一系列的BusinessObject所完成业务逻辑功能,系统要求在每一次业务逻辑处理时要做日志记录。这里我们略去具体的业务逻辑代码。
public interface BusinessInterface {
public void processBusiness();
}
public class BusinessObject implements BusinessInterface {
private Logger logger = Logger.getLogger(this.getClass().getName());
public void processBusiness(){
JAVA的反射机制与动态代理
李海峰(QQ:61673110)-Andrew830314@
运行时类型信息(RunTime Type Information,RTTI)使得你在程序运行时发现和使用类型
信息。RTTI主要用来运行时获取向上转型之后的对象到底是什么具体的类型。
1.Class对象:
JAVA使用Class对象来执行RTTI。每个类都有一个Class对象,它用来创建这个类的所有
对象,反过来说,每个类的所有对象都会关联同一个Class对象(对于数组来说,维数、类
型一致的数组的Class对象才是相同的),每个对象的创建都依赖于Class对象的是否创建,
Class对象的创建发生在类加载(ng.ClassLoader)的时候。
ng.Class类实现了Serializable、GenericDeclaration、Type、AnnotatedElement四个接口,
分别实现了可序列化、泛型定义、类型、元数据(注解)的功能。
你可以把Class对象理解为一个类在内存中的接口代理(它代理了这个类的类型信息、方法
签名、属性),JVM加载一个类的时候首先创建Class对象,然后创建这个类的每个实例的
时候都使用这个Class对象。
Class只有一个私有的无参构造方法,也就是说Class的对象创建只有JVM可以完成。
如何验证同一个类的多个对象的Class对象是一个呢? Cf1 cf1 = new Cf1();
Class clazz = Cf1.class;
System.out.println(cf1.getClass() == clazz);
我们知道==用来比较引用是否相等(也就是同一个引用),上面的输出语句结果是true。那
么Class对象是否相等是JAVA对象中唯一可以使用==判断的。
如何获取Class对象:
1.所有的引用数据类型(类-类型)的类名、基本数据类型都可以通过.class方式获取其Class
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,
对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎
么通过AOP来满足的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而
AOP的原理就是java的动态代理机制,所以本篇随笔就是对java的动态机制进行一个回
顾。
在java的动态代理机制中,有两个重要的类或接口,一个是InvocationHandler(Interface)、
另一个则是Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。首先我们
先来看看java的API帮助文档是怎么样对这两个类进行描述的:
InvocationHandler:InvocationHandleristheinterfaceimplementedbytheinvocationhandlerofaproxyinstance.
Eachproxyinstancehasanassociatedinvocationhandler.Whenamethodisinvokedonaproxyinstance,themethodinvocationisencodedanddispatchedtotheinvokemethodofitsinvocationhandler.
每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都
关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被
转发为由InvocationHandler这个接口的invoke方法来进行调用。我们来看看
InvocationHandler这个接口的唯一一个方法invoke方法:
Objectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable
java动态代理分析
为什么要使⽤代理。
先看⼀个简单的使⽤案例
1 import ng.reflect.Proxy;
2
3 public class ProxyTest {
4
5 public static void main(String[] args) {
6 //开启保存代理类
7 System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
8
9 Proxy.newProxyInstance(ProxyTest.class.getClassLoader(), new Class[]{ProxyDemo.class}, new InvocationHandlerDemo());
10
11 }
12 }
Proxy.newProxyInstance⽅法传⼊三个参数,类加载器,需要被代理的接⼝,代理类处理接⼝。结果返回的是Object对象。
jdk版本1.7,源码如下:
public static Object newProxyInstance(ClassLoader loader,
Class[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
if (h == null) {
throw new NullPointerException();
}
//检查权限 final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
}
//⽣成代理类,核⼼是这个⽅法
Class cl = getProxyClass0(loader, interfaces);
软件开发与设计 SOFTWARE DEVELOPMENT AND DESIGN
JSP页面启动Java应用程序的原理与实现
李安东 。王余旺。
(1.安徽T程技术学校,宿州234000;2.安徽理工大学现代教育技术中心,淮南232000)
摘要:由JSP页面启动Java应用程序在Web应用中有时可能是一件很有意义的工作。在某些专用的Web应用系
统中,服务器往往既要响应客户端的页面请求,又要做一些后台的处JE-z-作。有些处理可能还需要人工的参与和操
作,比如启动和关闭一个Java后台程序等等。通过用户自定义的标签,在标签的处理类中加入启动Java程序的代 码。同时对Java程序作必要的调整,即可实现由JSP页面启动Java程序,可以使所有管理和使用系统的操作全部通
过JSP页面来完成。当这样的Java程序很多时,会给管理、维护和使用系统带来很大的便利,对于不熟悉Java语言
的用户尤为如此。实现了对系统的集中化管理,提高了系统的集成度和专业化程度。这种方法还有一个明显的优.董
就是它与平台无关。 关键词:JSP;Java;Swing;JSP页面启动Java程序;平台无关性
The Principle and Implementation of Starting A Java Application from JSP Page
LI Andong ̄,WANG Yuwang2
(1・Engineering and Technology School of Anhui,Suzhou 234000
2.Center of Modem Educational Technology,Anhui University of Science and Technology,Huainan 232000)
【Abstract】It is very useful for people to launch a java application via jsp page in many web application systems.In some web systems,a server often has to do something in backend while it makes response in frontend for clients requesting jsp pages.Some processes may also need to engage in human control and manual operation,for example,starting and exiting a java program in backend and SO forth.The implementation of launching a java application from jsp page can be carried out from custom tag through adding some pieces of codes into the tag handler class and adjusting the java application itself,SO that all tasks of management,maintenance and operation of a web application system can be simply done completely in a jsp page.On the other hand,however,it's especially convenient for users who are not familiar with java language and when there are a lot of such java applications in a system.The centralized management of system mentioned above can also impmve integration and specialization of application systems.Apparently,this method is platform—independent because it is based on java and jsp. 【Keywords】JSP;Java;Swing;start a Java application via JSP page;platform-independent
JAVA实现动态⼆维码输出
⼀、控制层
1 @GetMapping(value = "/generate")
2 @ResponseBody
3 public void generateQR(@RequestParam("url")String url, HttpServletResponse response) {
4 BufferedImage imageWithLogo;
5 response.setHeader("Pragma", "No-cache");
6 response.setHeader("Cache-Control", "no-cache");
7 response.setDateHeader("Expires", 0);
8 response.setContentType("image/jpeg");
9 InputStream resourceAsStream = this.getClass().getResourceAsStream("/logo/logo.png");
10 imageWithLogo = QRCodeUtil.createImageWithLogo(url, resourceAsStream, true);
11 try(ServletOutputStream sos = response.getOutputStream()){
12 ImageIO.write(imageWithLogo, "jpeg", sos);
13 } catch (IOException e) {
14 e.printStackTrace();
15 }
16 }
⼆、QRCodeUtil
1 package .utils;
2
3 import com.google.zxing.BarcodeFormat;
4 import com.google.zxing.EncodeHintType;
Java实现HTTP代理服务器
Java 实现HTTP代理服务器
1. 主服务,⽤来侦听端⼝:
package org.javaren.proxy;
import .ServerSocket;
import .Socket;
publicclassSocketProxy{
/**
* @param args
*/
publicstaticvoid main(String[] args)throwsException{
ServerSocket serverSocket =newServerSocket(8888);
while(true){
Socket socket =null;
try{
socket = serverSocket.accept();
newSocketThread(socket).start();
}catch(Exception e){
e.printStackTrace();
}
}
}
}
2. 核⼼代码,处理链接的代理线程,内部设计了Socket的认证:
package org.javaren.proxy;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import .Socket;
publicclassSocketThreadextendsThread{
privateSocket socketIn;
privateInputStream isIn;
privateOutputStream osIn;
//
privateSocket socketOut;
privateInputStream isOut;
privateOutputStream osOut;
publicSocketThread(Socket socket){
动态代理实现Authorization(授权)
*
ng.reflect包中的 Proxy和InvocationHandler接口提供了创建(指定类[接口更准确些]的)动态代理类的能力。
我们知道,对象是类的实例,一般使用内存来模拟对象,对象是依据类为模板来创建的,创建时使用new来分配一块内存区(其布局
参考相应类的内存布局) ,为变量做一些赋值便是对象的初始化了。我们知道通常类是设计时的产物,在设计时我们编写对象的模板(即——类),运行时
产生类的实例。类所处的文件是 .java文件——源文件,之后编译为jvm-----java虚拟机可解释执行的.class字节码文件,在类解析
过程中这些.class文件由类加载器加载到虚拟机(可实现自己的类加载器来加载处于特定路径下的类,或加载用某种加密算法加密过的类文件---这样
便于进行安全控制——具体描述参考(Core java ——Java核心卷二))。在遇到创建对象的指令时使用加载的类来创建对象内存
空间。动态代理是不用创建类文件(当然也不用创建java源文件),就能在虚拟机中构造出类文件区域来(相当于使用Proxy类来
创建一块类内存区域,该区域中的内容相当于加载某个.class文件产生的区域;比如我们在使用DOM技术时,从一个XML文件构造一个
DOM内存表示,它是XML文件的内存表示,但我们也可以直接使用DOM API在内存中构建一个dom树,最终结果就是一个内存DOM树,你不用关心
这个dom树是来自于xmL文件还是直接的运行时构造)。
*
**
关于代理设计模式,这里不再敷述。代理和被代理类(目标类)实现共同的接口。我们在调用时不需区别它是否是真正的目标对象。
代理会转发请求到目标对象的。比如互联网上的代理服务器,我们不必关心它是不是代理,就当它不存在一样。对客户调用端
他是不关心具体是谁来提供这个服务功能;在服务端选择使用代理的原因可能是:安全,日志,防火墙等。就是说代理可提供一些
使用 JAVA 中的动态代理实现数据库连接池
刘冬 (u@), 珠海市创我科技发展有限公司软件工程师
简介: 作者通过使用 JAVA 中的动态代理实现数据库连接池,使使用者可以以普通的 jdbc
连接的使用习惯来使用连接池。
发布日期: 2002 年 12 月 05 日
级别: 初级
访问情况 : 20490 次浏览
评论: 4 (查看 | 添加评论 - 登录)
平均分 (43个评分)
为本文评分
数据库连接池在编写应用服务是经常需要用到的模块,太过频繁的连接数据库对服务性能来讲是一个瓶颈,使用缓冲池技术可以来消除这个瓶颈。我们可以在互联网上找到很多关于数据库连接池的源程序,但是都发现这样一个共同的问题:这些连接池的实现方法都不同程度地增加了与使用者之间的耦合度。很多的连接池都要求用户通过其规定的方法获取数据库的连接,这一点我们可以理解,毕竟目前所有的应用服务器取数据库连接的方式都是这种方式实现的。但是另外一个共同的问题是,它们同时不允许使用者显式的调用 Connection.close()
方法,而需要用其规定的一个方法来关闭连接。这种做法有两个缺点:
第一:改变了用户使用习惯,增加了用户的使用难度。
首先我们来看看一个正常的数据库操作过程:
int executeSQL(String sql) throws SQLException
{
Connection conn = getConnection(); // 通过某种方式获取数据库连接
PreparedStatement ps = null;
int res = 0;
try{
ps = conn.prepareStatement(sql);
res = ps.executeUpdate();
}finally{
try{
ps.close();
}catch(Exception e){}
JAVA动态代理使⽤⽰例和原理
代理模式
为其他对象提供⼀个代理以控制对某个对象的访问。代理类主要负责为委托了(真实对象)预处理消息、过滤消息、传递消息给委托类,代理类不现实具体服务,⽽是利⽤
委托类来完成服务,并将执⾏结果封装处理。
其实就是代理类为被代理类预处理消息、过滤消息并在此之后将消息转发给被代理类,之后还能进⾏消息的后置处理。代理类和被代理类通常会存在关联关系(即上⾯提到
的持有的被代理对象的引⽤),代理类本⾝不实现服务,⽽是通过调⽤被代理类中的⽅法来提供服务。
静态代理
创建⼀个接⼝,然后创建被代理的类实现该接⼝并且实现该接⼝中的抽象⽅法。之后再创建⼀个代理类,同时使其也实现这个接⼝。在代理类中持有⼀个被代理对象的引
⽤,⽽后在代理类⽅法中调⽤该对象的⽅法。
接⼝:
public interface HelloInterface {
void sayHello();
}
被代理类:
public class Hello implements HelloInterface{
@Override
public void sayHello() {
System.out.println("Hello zhanghao!");
}
}
代理类:
public class HelloProxy implements HelloInterface{
private HelloInterface helloInterface = new Hello();
@Override
public void sayHello() {
System.out.println("Before invoke sayHello" );
helloInterface.sayHello();
System.out.println("After invoke sayHello");
}
}
代理类调⽤:
被代理类被传递给了代理类HelloProxy,代理类在执⾏具体⽅法时通过所持⽤的被代理类完成调⽤。
Java动态代理与反射详解
⾸先我得先请⼤家不要误会,博客园说转载的⽂章放在⽂章分类⾥,原创的⽂章⽤随笔写,我开先还以为随笔是拿来写抒情⽂的(滑稽),
后来才发现不是这样的,但是⾃⼰所有的⽂章都在⽂章分类⾥了,⼜懒得搬运,所以我就⽤js重定向了⼀下。所以现在标题栏⾥进来的都是
⽂章分类哦,⼤部分都是⾃⼰原创的,转载会注明转载的url。
废话不多说,今天我想来聊⼀下java⾥的反射和动态代理的问题,因为这两个东西实在撩⼈,⽽且动态代理百度⼏乎都是千篇⼀律,今天我
写这篇博⽂希望能帮助⼤家,顺便也是为了巩固⾃⼰,毕竟⾃⼰也折腾了好久。
先来看看反射。
java⾥的class⽂件加载分为两种情况,⼀种就是类型是编译器已知的,这种⽂件的.class⽂件在编译的时候,编译器会把.class⽂件打开检
查,但是注意不是加载哦,第⼆种就是我们可能是从别的地⽅获取到了⼀个引⽤,然后动态的把这个未知类型的引⽤的对象的.class⽂件加
载进jvm虚拟机⾥。
那么我们称前者为RTTI,即Run- Time Type Identification 运⾏时类型识别,有的⼈把RTTI翻译成 Run - Time Type Information ,我个⼈认为
是不对的,因为我觉得它概括的不够全⾯,所以我建议⼤家把I 翻译成Identification更容易理解。
我们称后者为“反射”,这对于正在学习JAVA的⼈来说可是⼀个新的名词,但反射也是作为⼀个java的核⼼技术的存在。下⾯就来看看反射究
竟有多重要吧。
反射
在java⾥提供了⼀个叫做reflect的库,这个库⾥封装了Method,Constructor,field,Proxy,InvocationHandler 等类,这些类的API在我们学习反
射会很有帮助。
反射最⼤的作⽤就在于我们可以不在编译时知道某个对象的类型,⽽在运⾏时得到。同时我们只需要得到我们想得到的类的名字即可(如果
不在⼀个包,必须写完整的名字包括包名)。
Java实现动态代理的两种⽅式
Java领域中,常⽤的动态代理实现⽅式有两种,⼀种是利⽤JDK反射机制⽣成代理,另外⼀种是使⽤CGLIB代理。
JDK代理必须要提供接⼝,⽽CGLIB则不需要,可以直接代理类。下⾯分别举例说明。
1.JDK动态代理:
public interface People {
public void sayHello();
}
public class Chinese implements People {
@Override
public void sayHello() {
System.out.println("Chinese say hello.");
}
}
import ng.reflect.InvocationHandler;
import ng.reflect.Method;
public class PeopleInvocationHandler implements InvocationHandler{
private Object peolple;
Intermediary(Object people){
this.people = people;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object invoke = method.invoke(people, args);
System.out.println("-------- end ---------");
return invoke;
}
}
import ng.reflect.Proxy;
public class Test {
public static void main(String[] args) {
People chinese = new People();
Java多态实现原理
Java多态概述
多态是⾯向对象编程语⾔的重要特性,它允许基类的指针或引⽤指向派⽣类的对象,⽽在具体访问时实现⽅法的动态绑定。Java 对于⽅法
调⽤动态绑定的实现主要依赖于⽅法表,但通过类引⽤调⽤(invokevitual)和接⼝引⽤调⽤(invokeinterface)的实现则有所不同。
类引⽤调⽤的⼤致过程为:Java编译器将Java源代码编译成class⽂件,在编译过程中,会根据静态类型将调⽤的符号引⽤写到class⽂件
中。在执⾏时,JVM根据class⽂件找到调⽤⽅法的符号引⽤,然后在静态类型的⽅法表中找到偏移量,然后根据this指针确定对象的实际类
型,使⽤实际类型的⽅法表,偏移量跟静态类型中⽅法表的偏移量⼀样,如果在实际类型的⽅法表中找到该⽅法,则直接调⽤,否则,认为
没有重写⽗类该⽅法。按照继承关系从下往上搜索。 接⼝引⽤调⽤后⾯再说吧。
从上图可以看出,当程序运⾏时,需要某个类时,类载⼊⼦系统会将相应的class⽂件载⼊到JVM中,并在内部建⽴该类的类型信息(这个
类型信息其实就是class⽂件在JVM中存储的⼀种数据结构),包含java类定义的所有信息,包括⽅法代码,类变量、成员变量、以及本博⽂
要重点讨论的⽅法表。这个类型信息就存储在⽅法区。
注意,这个⽅法区中的类型信息跟在堆中存放的class对象是不同的。在⽅法区中,这个class的类型信息只有唯⼀的实例(所以是各个线程
共享的内存区域),⽽在堆中可以有多个该class对象。可以通过堆中的class对象访问到⽅法区中类型信息。就像在java反射机制那样,通
过class对象可以访问到该类的所有信息⼀样。
【重点】
⽅法表是实现动态调⽤的核⼼。上⾯讲过⽅法表存放在⽅法区中的类型信息中。为了优化对象调⽤⽅法的速度,⽅法区的类型信息会增加⼀
个指针,该指针指向⼀个记录该类⽅法的⽅法表,⽅法表中的每⼀个项都是对应⽅法的指针。
这些⽅法中包括从⽗类继承的所有⽅法以及⾃⾝重写(override)的⽅法。
Java实现动态数组
普通数组的元素个数是固定的,当数组满了之后要怎么办?数组要有多⼤才合适,有时提前并不知道。所以希望能够在运⾏时具有改变数组⼤⼩的能⼒。
动态数组就可以在任何时候改变⼤⼩。动态数组是指在声明时没有确定数组的⼤⼩,使⽤动态数组的优点是可以根据⽤户需求,有效利⽤存储空间。
假如有⼀个班级对象clazz,这有⼀个⽅法addStudent,这个⽅法的参数是Student对象,当我们调⽤addStudent⽅法添加学⽣时,在clazz对象中有⼀个students数组来存放
学⽣对象,但是当数组满了后,就要创建⼀个新的数组,这个数组要⽐原数组⼤,并把原数组中的学⽣对象转移到新数组中,并把原数组释放了,这样就成了动态数组,只要调⽤
addStudent者愿意,它就可以⼀直给clazz添加学⽣。开发中当数组满时,创建的新数组⼤⼩不会是⽐原数组多⼀个元素,这样会在后续加⼊学⽣时,每次都创建新数组,转移数组
元素,释放原数组,效率太低,往往创建的新数组⼤⼩是原数组的1.5倍⼤⼩。
实现
import java.util.Arrays;
/**
* copyright(c)2021 zbh.ALL rights Reserved
*
* 描述:
*
* @author zbh
* @version 1.0
* @date 2021/2/23
*/
public class Demo6 {
/**
* 初始数组⼤⼩
*/
private static final int INIT = 4;
/**
* 存储数据数组
*/
int[] arr;
/**
* 当前位置
*/
int index = 0;
/**
* ⽆参默认的构造⽅法
*/
public Demo6() {
// 构造⽅法嵌套调⽤,直接写this,不写⽅法名
// 此代码只能是第⼀⾏
this(INIT);
}
/**
* 初始化对象
*
* @param capacity 数组初始值
1 / 27 Java动态代理机制详解 class文件简介及加载 Java编译器编译好Java文件之后,产生.class 文件在磁盘中。这种class文件是二进制文件,内容是只有JVM虚拟机能够识别的机器码。JVM虚拟机读取字节码文件,取出二进制数据,加载到内存中,解析.class 文件内的信息,生成对应的 Class对象: class字节码文件是根据JVM虚拟机规范中规定的字节码组织规则生成的。 下面通过一段代码演示手动加载 class文件字节码到系统内,转换成class对象,然后再实例化的过程: a. 定义一个 Programmer类: 1. package samples; 2. /** 3. * 程序猿类 4. * 5. */ 6. public class Programmer { 7. 8. public void code() 9. { 10. System.out.println("I'm a Programmer,Just Coding....."); 11. }
2 / 27 12. } b. 自定义一个类加载器: 1. package samples; 2. /** 3. * 自定义一个类加载器,用于将字节码转换为class对象 4. * 5. */ 6. public class MyClassLoader extends ClassLoader { 7. 8. public Class defineMyClass( byte[] b, int off, int len) 9. { 10. return super.defineClass(b, off, len); 11. } 12. 13. } c. 然后编译成Programmer.class文件,在程序中读取字节码,然后转换成相应的class对象,再实例化: 1. package samples; 2. 3. import java.io.File; 4. import java.io.FileInputStream; 5. import java.io.FileNotFoundException; 6. import java.io.IOException; 7. import java.io.InputStream; 8. import .URL; 9. 10. public class MyTest { 11. 12. public static void main(String[] args) throws IOException { 13. //读取本地的class文件内的字节码,转换成字节码数组 14. File file = new File("."); 15. InputStream input = new FileInputStream(file.getCanonicalPath()+"\\bin\\samples\\Programmer.class"); 16. byte[] result = new byte[1024]; 17. 18. int count = input.read(result); 19. // 使用自定义的类加载器将 byte字节码数组转换为对应的class对象 20. MyClassLoader loader = new MyClassLoader(); 21. Class clazz = loader.defineMyClass( result, 0, count);
java注解实现代理
使⽤注解来实现代理。主要使⽤三个⾃定义的类。如下。
⼀,枚举类,有前后两种。
1 package cn.jxlys.util;
2
3 /**
4 * 代理的类型,前还是后
5 *
6 * @author jxlys
7 *
8 */
9 public enum ProxyType {
10 BEFORE(ProxyBase.BEFORE_STRING), AFTER(ProxyBase.AFTER_STRING);
11 public String value;
12
13 private ProxyType(String value) {
14 this.value = value;
15 }
16
17 }
⼆,注解类。
1 package cn.jxlys.util;
2
3 import static cn.jxlys.util.ProxyType.*;
4 import static ng.annotation.ElementType.METHOD;
5 import static ng.annotation.ElementType.TYPE;
6
7 import ng.annotation.Retention;
8 import ng.annotation.RetentionPolicy;
9 import ng.annotation.Target;
10
11 /**
12 * ⾃定义的注解代理对象:必须是接⼝对象赋值实现类
13 *
14 * @author jxlys
15 */
16 @Retention(RetentionPolicy.RUNTIME)
17 @Target(value = { TYPE, METHOD })
18 public @interface JsProxy {
19
20 /**
java动态代理的实现原理
Java动态代理是通过在运行时创建代理类来实现的。在Java中,动态代理是通过`ng.reflect.Proxy`类实现的。它允许在运行时创建一个实现一组接口的代理类,这些代理类可以将方法调用分派到一个实现了`InvocationHandler`接口的对象上。
实现动态代理的关键在于`InvocationHandler`接口,它只有一个方法`invoke`,当代理对象的方法被调用时,`invoke`方法会被调用,从而允许对方法调用进行拦截和处理。
具体实现步骤包括:
1. 定义一个`InvocationHandler`接口的实现类,该类负责实际处理代理对象的方法调用。
2. 使用`Proxy`类的`newProxyInstance`方法来创建代理对象,该方法需要传入类加载器、要实现的接口列表和`InvocationHandler`实现类的实例。
3. 当代理对象的方法被调用时,`InvocationHandler`的`invoke`方法将被调用,可以在该方法中对方法调用进行拦截和处理。
总的来说,动态代理的实现原理就是在运行时动态创建一个代理类,该代理类实现了指定的接口,并将方法调用分派到`InvocationHandler`的`invoke`方法上,从而实现对方法调用的拦截和处理。