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在我们学习反射会很有帮助。
反射最大的作用就在于我们可以不在编译时知道某个对象的类型,而在运行时得到。同时我们只需要得到我们想得到的类的名字即可(如果不在一个包,必须写完整的名字包括包名)。
package com.bike;
import java.lang.reflect.*;
public class Main {
public static void main(String[] args) throws Exception{
//返回A的构造方法
Constructor c = A.class.getConstructor();
//返回A类的所有为public 声明的构造方法
Constructor[] cons = A.class.getConstructors();
//返回A类所有的构造方法,包括private
Constructor[] cons2 = A.class.getDeclaredConstructors();
//返回A类的第一个public 方法
Method m = A.class.getMethod("say");
//执行
m.invoke(A.class.newInstance(), null);
//返回A类所有的public 方法
Method[] ms = A.class.getMethods();
//返回A类所有的方法,包括private
Method[] allMs = A.class.getDeclaredMethods();
//返回A类的public字段
Field field = A.class.getField("i");
System.out.println(field.get(A.class.newInstance()));
//返回A类的static 字段
System.out.println(field.get(null));
}
}
class A{
public int i = 1;
public static int b = 2;
public A(){
System.out.println("无参构造");
}
private A(String s){
System.out.println("有参构造"+s);
}
public void say(){
System.out.println("say");
}
}
这里我只是简单的把API罗列了一下,大家可以自己动手试试,我这里就不再去描述了。
通过上面的例子我们可以看出我们只用知道一个类的名字便可以得知它内部方法和字段,那么这里已经强烈的体现到了反射的作用。只是我这里做例子的时候把A作为了自己内部包的一个类,而在实际开发中,你可能是跨包的,所以你必须要写上全名才行。
关于.class类字面常量的知识请参照我的上一篇博文:http://www.cnblogs.com/haodawang/articles/5954368.html
代理
接下来我们来看一下代理。
代理可以帮助我们进行很好的封装,使底层的代码能够有效的隐藏起来。
为了区别,我们先来看看静态代理吧。
public class Main2 {
//这里传入的是接口类型的对象,方便向上转型,实现多态
public static void consumer(ProxyInterface pi){
pi.say();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
consumer(new ProxyObject());
}
}
//代理接口
interface ProxyInterface{
public void say();
}
//被代理者
class RealObject implements ProxyInterface{
//实现接口方法
@Override
public void say() {
// TODO Auto-generated method stub
System.out.println("say");
}
}
//代理者
class ProxyObject implements ProxyInterface{
@Override
public void say() {
// TODO Auto-generated method stub
//dosomething for example
System.out.println("hello proxy");
new RealObject().say();
System.out.println("this is method end");
}
}
output:
hello proxy
say
this is method end
这就是静态代理,理解这个应该不难。
下面我们再来看看动态代理
import java.lang.reflect.*;
public class Main {
static void customer(ProxyInterface pi){
pi.say();
}
public static void main(String[] args){
RealObject real = new RealObject();
ProxyInterface proxy = (ProxyInterface)Proxy.newProxyInstance(ProxyInterface.class.getClassLoader(),new Class[]{ProxyInterface.class}, new ProxyObject(real));
customer(proxy);
}
}
interface ProxyInterface{
void say();
}
//被代理类
class RealObject implements ProxyInterface{
public void say(){
System.out.println("i'm talking");
}
}
//代理类,实现InvocationHandler 接口
class ProxyObject implements InvocationHandler{
private Object proxied = null;
public ProxyObject(){
}
public ProxyObject(Object proxied){
this.proxied = proxied;
}
public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
System.out.println("hello");
return arg1.invoke(proxied, arg2);
};
}
可以看到动态代理的代理类是实现了一个InvocationHandler的接口,我们通过reflect.Proxy的类的newProxyInstance方法就可以得到这个接口的实例,然后再来作为参数传递进去,这里每一个在代理类上处理的东西也会被重定向到调用处理器上。
至于动态代理和静态代理的区别,即动态代理是动态的创建代理和动态的处理方法的,这也是反射的一个重要体现之处。
Java动态代理与反射详解的更多相关文章
- 5.java动态代理、反射
1.java动态代理.反射(IDEA导入JUnit4) 1.1.反射 通过反射的方式可以获取class对象中的属性.方法.构造函数等 1.2.反射代码 import java.io.Serializa ...
- Java 动态代理与反射机制
java动态代理必须的两个类与两个接口: 首先需要有一个接口(委托者需要实现该接口的方法)示例如下: <pre name="code" class="html&qu ...
- Java基础13:反射详解
本节主要介绍Java反射的原理,使用方法以及相关的技术细节,并且介绍了关于Class类,注解等内容. 具体代码在我的GitHub中可以找到 https://github.com/h2pl/MyTech ...
- Java动态代理和反射机制
反射机制 Java语言提供的一种基础功能,通过反射,我们可以操作这个类或对象,比如获取这个类中的方法.属性和构造方法等. 动态代理:分为JDK动态代理.cglib动态代理(spring中的动态代理). ...
- Mybatis mapper动态代理的原理详解
在开始动态代理的原理讲解以前,我们先看一下集成mybatis以后dao层不使用动态代理以及使用动态代理的两种实现方式,通过对比我们自己实现dao层接口以及mybatis动态代理可以更加直观的展现出my ...
- 详解java动态代理机制以及使用场景
详解java动态代理机制以及使用场景 https://blog.csdn.net/u011784767/article/details/78281384 深入理解java动态代理的实现机制 https ...
- JAVA高级架构师基础功:Spring中AOP的两种代理方式:动态代理和CGLIB详解
在spring框架中使用了两种代理方式: 1.JDK自带的动态代理. 2.Spring框架自己提供的CGLIB的方式. 这两种也是Spring框架核心AOP的基础. 在详细讲解上述提到的动态代理和CG ...
- JAVA动态代理详解
1.什么是代理 代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等. 2.什么是动态代理 在程 ...
- java动态代理使用详解
我们都知道AOP的原理就是java的动态代理机制,下面我就对java的动态代理机制进行学习与总结 java动态代理的实现有两个重要的类: Proxy:类 作用就是用来动态创建一个代理对象的类 Invo ...
随机推荐
- react和vue的异同点
一.相似处1.使用Virtual DOM,都有jsx,性能好.2.提供了响应式(reactive)和可组合的视图组件(composable view component).3.将注意力集中保持在核心库 ...
- unity3d 给游戏添加音源 Unity3d adds a sound source to the game
unity3d 给游戏添加音源 Unity3d adds a sound source to the game 作者:韩梦飞沙 Author:han_meng_fei_sha 邮箱:3131345 ...
- Altium Designer Summer 09 Gerber 文件设置
- 图的 储存 深度优先(DFS)广度优先(BFS)遍历
图遍历的概念: 从图中某顶点出发访遍图中每个顶点,且每个顶点仅访问一次,此过程称为图的遍历(Traversing Graph).图的遍历算法是求解图的连通性问题.拓扑排序和求关键路径等算法的基础.图的 ...
- 自己对war包解压的误区
ss.war解压后不会出现ss而是startup.sh运行后会出现
- AngularJS中使用Karma单元测试初体验
■ 搭建karma测试环境 → 创建app和test文件夹→npm install karma --save-dev→npm install karma-jasmine --save-dev→npm ...
- 转: chrome64打开弹出窗flash的办法
https://jingyan.baidu.com/article/380abd0a38f0411d90192c2e.html
- SQLSERVER 2012 之 “代理 XP”组件已作为此服务器安全配置的一部分被关闭
新建维护计划的时候遇到下图的报错信息 标题: Microsoft SQL Server Management Studio ------------------------------ “代理 XP” ...
- mysql insert锁机制
https://blog.csdn.net/zhanghongzheng3213/article/details/53436240
- WineBottler for Mac(Mac 运行 exe 程序工具)安装
1.软件简介 WineBottler 是 macOS 系统上一款模拟 Windows 环境的工具,让你能够在 Mac 上安装 Windows 软件,类似于知名的 Crossover,但 Wine ...