Java动态代理和反射机制
反射机制
Java语言提供的一种基础功能,通过反射,我们可以操作这个类或对象,比如获取这个类中的方法、属性和构造方法等。
动态代理:分为JDK动态代理、cglib动态代理(spring中的动态代理)。
静态代理
预先(编译期间)确定了代理者与被代理者之间的关系,也就是说,若代理类在程序运行前就已经存在了,这种情况就叫静态代理
动态代理
代理类在程序运行时创建的代理方式。也就是说,代理类并不是在Java代码中定义的,而是在运行期间根据我们在Java代码中的“指示”动态生成的。
动态代理比静态代理的优势在于:
动态代理可以很方便的对代理类的函数进行统一的处理(invoke),而不是修改每个代理类的函数,更灵活和扩展。
JDK的动态代理(依赖于接口)
在Java的动态代理机制中,有两个重要的类或接口,一个是InvocationHandler接口,另一个是Proxy类。
InvocationHandler接口是给动态代理类实现的,负责处理被代理对象的操作
Proxy类是用来创建动态代理类实例对象的,只有得到这个对象,才能调用需要代理的方法。
动态代理的代理类是在静态代理类上进行修改,将动态代理类实现InvocationHandler接口,重写Invoke方法,Invoke方法通过传入的被代理类方法和参数来执行。
如下实例:
public interface AppService {
void createApp(String name);
void deleteApp(String name);
}
//代理类(比如微商代理)
public class AppServiceImpl implements AppService{
@Override
public void createApp(String name) {
System.out.print("App["+name+"] has been created.");
}
@Override
public void deleteApp(String name) {
System.out.print("App["+name+"] has been delete.");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class LoggerInterceptor implements InvocationHandler {
private Object target; //委托类(被代理类)的实例,比如厂家
public LoggerInterceptor(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
System.out.println("Entered "+target.getClass().getName()+"-"+method.getName()+",with arguments{"+args[0]+"}");
Object result = method.invoke(target, args);
//调用目标对象的方法 (调用厂家的方法(createApp)及参数(Kevin Test))
System.out.println("Before return:"+result);
return result;
}
}
import java.lang.reflect.Proxy;
public class test {
public static void main(String[] args) {
AppService target = new AppServiceImpl();//生成目标对象 (代理类的对象)
//接下来创建代理对象
AppService proxy = (AppService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(), new LoggerInterceptor(target));
proxy.createApp("Kevin Test1");
proxy.deleteApp("Kevin Test2");
}
}
/**
* 1、jdk的动态代理实现方式是依赖于接口的,首先使用接口来定义好操作规范。
* 2、通过proxy类产生的代理对象调用被代理对象的操作。
* 3、而这个操作又被分发给InvocationHandler接口的invoke方法具体执行
*
* 在java的动态代理机制中,有两个重要的类或接口,一个是InvocationHandler接口、另一个则是 Proxy类,这个类和接口是实现我们动态代理所必须用到的。
InvocationHandler接口是给动态代理类实现的,负责处理被代理对象的操作的,而Proxy是用来创建动态代理类实例对象的,因为只有得到了这个对象我们才能调用那些需要代理的方法。
*
* 此方法的参数含义如下
proxy:代表动态代理对象
method:代表正在执行的方法
args:代表当前执行方法传入的实参
返回值:表示当前执行方法的返回值
*
* 如上:
* 使用了Proxy类的newProxyInstance方法生成代理对象,然后用这个对象去调用createApp()和deleteApp()方法,
* 其实系统会将这2个方法分发给invoke()方法区执行。其中proxy对象的类是系统帮我们动态创建了,其实实现了我们的业务接口AppService
*
*/
cglib动态代理(继承方式)
cglib动态代理中使用MethodInterceptor来实现动态代理类。
拦截器MethodInterceptor中就是由MethodProxy的InvokSuper方法调用代理方法的。
MethodProxy类生成代理方法和代理方法的签名。
JDK动态代理和Cglib动态代理的区别:
1、JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。
2、Cglib因为是继承机制,所以无法代理被final修饰的方法。
3、JDK和Cglib都是在运行期间生产字节码,JDK是直接写class字节码,Cglib使用ASM框架写class字节码;cglib代理实现更复杂,生成代理类比JDK效率低。
4、JDK调用代理方法,是通过反射实现机制调用,cglib是通过Fashclass机制直接调用方法,效率更高。
Fastcalss机制:
为代理类和被代理类个生成一个class,这个class会为代理类或被代理类的方法分配一个index。
这个index当做一个入参,Fashclass就可以直接定位要调用的方法,并直接进行调用。这样省去了反射调用,所以效率高。
Java动态代理和反射机制的更多相关文章
- Java 动态代理与反射机制
java动态代理必须的两个类与两个接口: 首先需要有一个接口(委托者需要实现该接口的方法)示例如下: <pre name="code" class="html&qu ...
- 5.java动态代理、反射
1.java动态代理.反射(IDEA导入JUnit4) 1.1.反射 通过反射的方式可以获取class对象中的属性.方法.构造函数等 1.2.反射代码 import java.io.Serializa ...
- Java动态代理的实现机制
一.概述 代理是一种设计模式,其目的是为其他对象提供一个代理以控制对某个对象的访问,代理类负责为委托类预处理消息,过滤消息并转发消息以及进行消息被委托类执行后的后续处理.为了保持行为的一致性,代理类和 ...
- Java动态代理与反射详解
首先我得先请大家不要误会,博客园说转载的文章放在文章分类里,原创的文章用随笔写,我开先还以为随笔是拿来写抒情文的(滑稽),后来才发现不是这样的,但是自己所有的文章都在文章分类里了,又懒得搬运,所以我就 ...
- Java 动态代理机制分析及扩展
Java 动态代理机制分析及扩展,第 1 部分 王 忠平, 软件工程师, IBM 何 平, 软件工程师, IBM 简介: 本文通过分析 Java 动态代理的机制和特点,解读动态代理类的源代码,并且模拟 ...
- [转]Java 动态代理机制分析及扩展
引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执 ...
- Java 动态代理机制分析及扩展--转
http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/#icomments http://www.ibm.com/developerworks/c ...
- Java 动态代理机制分析及扩展,第 1 部分
Java 动态代理机制分析及扩展,第 1 部分 http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/ 本文通过分析 Java 动态代理的机制和特 ...
- 详解java动态代理机制以及使用场景
详解java动态代理机制以及使用场景 https://blog.csdn.net/u011784767/article/details/78281384 深入理解java动态代理的实现机制 https ...
随机推荐
- wildfly8+jpa EntityBean 简单入门
1)首先配置wildfly的数据源,我使用的是mysql数据库 1.jboss7开始,jboss使用模块化设计所以数据源的配置也是遵循模块化. 打开wildfly的安装目录进入modules\syst ...
- 第6章—渲染web视图—使用Apache Tiles视图定义布局
使用Apache Tiles视图定义布局 Tiles是一个免费的开源模板Java应用程序的框架.基于复合模式简化的用户界面的构建.对于复杂的网站仍是最简单.最优雅的方式与任何MVC技术一起工作.S ...
- 【C#小知识】C#中一些易混淆概念总结(六)---------解析里氏替换原则,虚方法 分类: C# 2014-02-08 01:53 1826人阅读 评论(0) 收藏
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...
- 【数组】Find Minimum in Rotated Sorted Array
题目: Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 ...
- web测试总结—用户体验
一.什么是用户体验 用户体验,英文叫做user experience,缩写为UE,或者UX.一个较常见的定义是“指用户访问一个网站或者使用一个产品时的全部体验.他们的印象和感觉,是否成功,是否享受,是 ...
- Java_反射机制详解
本篇文章依旧采用小例子来说明,因为我始终觉的,案例驱动是最好的,要不然只看理论的话,看了也不懂,不过建议大家在看完文章之后,在回过头去看看理论,会有更好的理解. 下面开始正文. [案例1]通过一个对象 ...
- SQL Function 自定义函数
目录 产生背景(已经有了存储过程,为什么还要使用自定义函数) 发展历史 构成 使用方法 适用范围 注意事项 疑问 内容 产生背景(已经有了存储过程,为什么还要使用自定义函数) 与存储过程的区别(存 ...
- javascript数组原型方法
1.javascript数组原型方法. <!DOCTYPE html> <html lang="en"> <head> <meta cha ...
- rails 5.2 启动警告 warning: previous definition of VERSION was here和bootsnap
bootsnap依赖问题 You should add gem 'bootsnap' to your gemfile to install it or remove the line require ...
- Linux进程管理 简介
何为进程,我想这个问题大家再熟悉不过了吧,无非就是"执行中的程序"! 概念性的东西本文暂时忽略或者略微一提,详细信息还需要阅读相应的blog或专业书籍.(博主收藏了计算机相关的大量 ...