一、反射

反射在之前的文章中详细的解释过了,简单概括就是:可以动态的获取到一个类内部的所有的信息,动态的去创建对象和使用对象以及可以操作对象的属性和方法。

二、代理

首先解释一下代理:使用一个代理对象将对象包装起来,然后用该代理对象来取代该对象,任何对原始对象的调用都要通过代理,代理对象决定是否以及何时调用原始对象的方法。

三、静态代理

静态代理:被代理对象和代理对象要实现同一套接口且代理对象内部要包含被代理对象,被代理对象覆盖重写接口方法,在方法内部加上实际业务上的增强。

代码目录

代码演示

//公共接口
public interface ZhangSanInterface {
//定义一个吃饭的抽象方法
void eat();
} //张三类
public class ZhangSan implements ZhangSanInterface {
@Override
public void eat() {
System.out.println("吃饭。。。"); //实现方法体
}
} //张三代理类
public class ZhangSanProxy implements ZhangSanInterface{ private ZhangSanInterface zhangSanInterface; public ZhangSanProxy(ZhangSanInterface zhangSanInterface) {
this.zhangSanInterface = zhangSanInterface;
} @Override
public void eat() {
System.out.println("饭前洗手。。"); //方法前增强
zhangSanInterface.eat();
System.out.println("饭后洗碗。。"); //方法后增强
}
} //测试类
public class Main01 {
public static void main(String[] args) {
ZhangSanProxy proxy = new ZhangSanProxy(new ZhangSan()); //代理对象中传入张三对象
proxy.eat();
}
}

总结:静态代理不需要使用反射机制就能够实现,但是也存在了很明显的缺陷,如果想要在加一些其他的被代理类,必须要修改代码,不符合开闭原则(对外扩展开放,对内修改关闭),扩展性差、维护性差。

四、动态代理

动态代理:在程序的执行时(动态),使用jdk的反射机制,创建对象的能力,创建的是代理类的对象,而不用我们自己创建类文件。

1、JDK动态代理

  使用java反射包中的类和接口实现动态代理的功能。 反射包 java.lang.reflect,里面有三个类:InvocationHandler、Method、Proxy 

  1) InvocationHandler接口(调用处理器) :就-一个方法invoke ( )
      invoke():表示代理对象要执行的功能代码。你的代理类要完成的功能就写在invoke ()方法中。
      代理类完成的功能:
    1.调用目标方法,执行目标方法的功能
    2.功能增强,在目标方法调用时,增加功能。

   方法原型:
   参数: object proxy :jdk创建的代理对象,无需赋值。
       Method method: 目标类中的方法,jdk提供me thod对象的
       object[] args: 目 标类中方法的参数,jdk提供的 。
     public object invoke (object proxy, Method method, Object[] args)
     InvocationHandler接口:表示你的代理要千什么。

      怎么用: 1.创建类实现接口Invocati onHandler
           2.重写invoke()方法,把原来静态代理中代理类要完成的功能,写在这。

  2) Method类:表示方法的,确切 的说就是目标类中的方法.
      作用:邇过Method可以执行某个目标类的方法,Method. invoke() ;
      method. invoke(目标对象,方法的参数)

  3) Proxy类: 核心的对象,创建代理对象。之前创建对象都是new类的构造方法(),现在我们是使用Proxy类的方法,代替new的使用。
      方法:静态方法 newProxyInstance ()
      作用是:创建代理对象, 等同于静态代理中的   代理类 proxy = new 代理类() ; 

   参数:
      1. ClassLoader loader 类加载器,负责向内存中加载对象的。使用反射获取对象的ClassLoader类a,a. getCalss () .getClassLoader(),目标对象的类加载器。
      2. Class<?>[] interfaces:接口,目标对象实现的接口,也是反射获取的。
      3. InvocationHandler h :我们自己写的,代理类要完成的功能。

   返回值:newProxyInstance () 的返回值就是代理对象。

  实现动态代理的步骤
    1.创建接口,定义目标类要完成的功能
    2.创建目标类实现接口
    3.创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
    1.调用目标方法
    2.增强功能
    4.使用Proxy类的静态方法,创建代理对象。并把返回值转为接口类型。

  代码目录

  代码展示

//目标接口
public interface Target {
void eat();
} //目标类
public class TargetImpl implements Target {
@Override
public void eat() {
System.out.println("吃饭饭。。");
}
} //必须实现InvocationHandler接口,完成动态代理要做的功能(1.调用目标方法 2.功能增强)
public class MyHandler implements InvocationHandler { private Object taget; public MyHandler(Object taget) {
this.taget = taget;
} //动态代理:对象是活动的,不是固定的,需要传进来
//传入是谁,就给谁创建代理。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("洗手手。。");
Object invoke = method.invoke(taget, args);//执行目标方法
System.out.println("洗碗碗。。");
return null;
}
} //主函数
public class Main02 {
public static void main(String[] args) {
//1、创建目标对象
Target taget = new TargetImpl(); //2、创建InvocationHandler对象
InvocationHandler handler = new MyHandler(taget); //3、创建代理对象
Target proxy = (Target) Proxy.newProxyInstance(
taget.getClass().getClassLoader(),
taget.getClass().getInterfaces(),
handler);
//4、通过代理执行方法
proxy.eat();
}
}

2、CGLIB动态代理

  cglib是第三方的工具类,创建代理对象。cglib原理是继承,通过继承目标类,创建它的子类,在子类中重写重写父类中同名的方法,实现功能修改/增强。cglib动态代理要求目标类能够被继承。

  目录展示

  代码展示

//目标类
public class Target {
public void eat(){
System.out.println("吃饭饭。。");
}
} //实现MethodInterceptor接口
public class CglibProxy implements MethodInterceptor {
private Object target; public CglibProxy(Object target) {
this.target = target;
} /**
* @param proxy 代理对象引用
* @param method 被代理对象的方法的描述引用
* @param objects 方法的参数
* @param methodProxy 代理对象的 对目标对象的方法的描述
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("洗手手。。");
method.invoke(target,objects);
System.out.println("洗碗碗。。");
return null;
}
} /主方法测试
public class Main03 {
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy(new Target());
Target target = (Target) Enhancer.create(Target.class, cglibProxy);
target.eat();
}
}

反射、静态代理、动态代理(jdk、cglib)的更多相关文章

  1. 静态代理,动态代理,Cglib代理详解

    一.静态代理 新建一个接口 定义一个玩家方法: package com."".proxy.staticc; public interface Iplayer { public vo ...

  2. 【SSH系列】静态代理&&动态代理

    从设计模式说起 代理模式是二十三中设计模式中的一种,代理模式就是指由一个代理主题来操作真实的主题,真实的主题执行具体的业务操作,而代理主题负责其她相关业务,简而言之,代理模式可以由以下三个部分组成: ...

  3. 8、Spring教程之静态代理/动态代理

    为什么要学习代理模式,因为AOP的底层机制就是动态代理! 代理模式: 静态代理 动态代理 学习aop之前 , 我们要先了解一下代理模式! 静态代理 静态代理角色分析 抽象角色 : 一般使用接口或者抽象 ...

  4. 轻松理解 Java 静态代理/动态代理

    目录 什么是代理模式 定义 代理模式的主要角色 优点 缺点 静态代理 动态代理 JDK原生动态代理 例子 分析 小结 CGLIB动态代理 例子 分析 final类型 其他方案 尾声 理解Java动态代 ...

  5. Java的反射机制和动态代理

    介绍Java注解的时候,多次提到了Java的反射API.与javax.lang.model不同的是,通过反射API可以获取程序在运行时刻的内部结构.反射API中提供的动态代理也是非常强大的功能,可以原 ...

  6. java静态和动态代理原理

    一.代理概念 为某个对象提供一个代理,以控制对这个对象的访问. 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代.代理类负责请求的预处理.过滤.将请求分派给委托类 ...

  7. java反射机制与动态代理

    在学习HadoopRPC时.用到了函数调用.函数调用都是採用的java的反射机制和动态代理来实现的,所以如今回想下java的反射和动态代理的相关知识. 一.反射 JAVA反射机制定义: JAVA反射机 ...

  8. Java反射机制以及动态代理

    Java反射机制以及动态代理 Java反射机制 含义与功能 Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类 ...

  9. Java 的静态代理 动态代理(JDK和cglib)

    转载:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是 ...

  10. Spring -07 -AOP [面向切面编程] - 使用注解@+ AspectJ 方式实现环绕/前/后等通知 -超简洁 --静态代理/动态代理{JDK/cglib}

    1.spring 不会自动去寻找注解,必须告诉 spring 哪些包下的类中可能有注解;使用注解来取代配置文件.1.1 引入xmlns:context ,指定扫描范围 <context:comp ...

随机推荐

  1. 人口信息普查系统-JavaWeb-三

    今天给大家分享前端主页面的代码,设有五个功能.涉及到增删改查,用到了超链接的跳转. <!DOCTYPE html> <html lang="en"> < ...

  2. Java多线程专题3: Thread和ThreadLocal

    合集目录 Java多线程专题3: Thread和ThreadLocal 进程, 线程, 协程的区别 进程 Process 进程提供了执行一个程序所需要的所有资源, 一个进程的资源包括虚拟的地址空间, ...

  3. Linux中date命令用法

    1.以下是服务器现在的时间,当前时间的各种表示方法,表示成自己想要的时间格式,后面的范例将会在这个时间基础之上进行演示,同时这也是熟练掌握后面各种date命令的前提,请读者注意 [root@RHEL6 ...

  4. Go 记录一次groutine通信与context控制

    需求背景: 项目中需要定期执行任务A来做一些辅助的工作,A的执行需要在超时时间内完成,如果本次执行超时了,那就不对本次的执行结果进行处理(即放弃这次执行).同时A又依赖B,C两个子任务的执行结果.B, ...

  5. 读取数据库Blob类型的文本数据

    开发一个查询功能时,遇到了一个ORM的问题:数据库字段是 Blob 类型,里面实际存储的是文本数据,Java 后端代码中用字符串 String 类型去接收这个字段的数据时,报错,提示没有对应的sett ...

  6. JVM学习八-(复习)年轻代、老年代、永久代

    Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象,如下图所示: 在 Java 中,堆被划分成两个不同的区域:新生代 ( Young ).老年代 ( Old).新生代 ...

  7. cross-env 作用

    是什么 运行跨平台设置和使用环境变量的脚本 出现原因 当您使用NODE_ENV =production, 来设置环境变量时,大多数Windows命令提示将会阻塞(报错). (异常是Windows上的B ...

  8. 【转】Nginx服务并发过10万的Linux内核优化配置

    http://www.linuxidc.com/Linux/2012-11/75151.htm以下Linux 系统内核优化配置均经在线业务系统测试,服务器运行状态良好,用了一些时间整理,现和大家分享一 ...

  9. latex知识点

    sensors期刊下载的laTex模板错误修改 把上面的那个删了,原因是什么那,请看下文...... 如何使用endnote + latex 1.使用word将文献按照word引用顺序导出成一个新的e ...

  10. [源码解析] NVIDIA HugeCTR,GPU 版本参数服务器 --(1)

    [源码解析] NVIDIA HugeCTR,GPU版本参数服务器 --(1) 目录 [源码解析] NVIDIA HugeCTR,GPU版本参数服务器 --(1) 0x00 摘要 0x01 背景 1.1 ...