Java静态代理&动态代理&Cglib代理详解
一、静态代理
根据被代理的类的时机的不同,如果在编译阶段就能确定下来的被代理的类是哪一个,那么,就可以使用静态代理的方式。
申明一个接口:
/**
* @author jiaqing.xu@hand-china.com
* @version 1.0
* @name
* @description
* @date 2018/7/23
*/
public interface Person {
void sayHello(String content, int age);
}
实现类,即需要被代理的类:
/**
* @author jiaqing.xu@hand-china.com
* @version 1.0
* @name
* @description 需要被代理的类 实现接口
* @date 2018/7/23
*/
public class Student implements Person {
@Override
public void sayHello(String content, int age) {
System.out.println("student say hello " + content + " "+ age);
}
}
实现类:
/**
* @author jiaqing.xu@hand-china.com
* @version 1.0
* @name
* @description
* @date 2018/7/23
*/
public class StaticProxyTest implements Person{
//接口对象
private Person o; public StaticProxyTest(Person o){
this.o = o;
} public static void main(String[] args) {
// TODO Auto-generated method stub
//s为被代理的对象,某些情况下 我们不希望修改已有的代码,我们采用代理来间接访问
//在代理类中引入被代理的对象
Student s = new Student();
//创建代理类对象 s是接口的实例
StaticProxyTest proxy = new StaticProxyTest(s);
//调用代理类对象的方法
proxy.sayHello("welcome to java", 20);
} @Override
public void sayHello(String content, int age) {
// TODO Auto-generated method stub
System.out.println("ProxyTest sayHello begin");
//在代理类的方法中 间接访问被代理对象的方法
o.sayHello(content, age);
System.out.println("ProxyTest sayHello end");
}
}
二、动态代理
如果不能在代码的编译阶段就去确定需要代理的类是哪一个的话,就可以使用类的动态代理机制,在代码运行期间去动态加载类的信息。
Java动态代理和Cglib方式的代理的重要区别:
Java动态代理只能对接口进行代理,如果要代理的类是一个普通的类,没有接口则需要使用Cglib来实现。
Java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
Cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
创建接口:
/**
* @author jiaqing.xu@hand-china.com
* @version 1.0
* @name
* @description
* @date 2018/7/23
*/
public interface IStudent {
void action();
}
/**
* @author jiaqing.xu@hand-china.com
* @version 1.0
* @name
* @description
* @date 2018/7/23
*/
public class StudentImpl implements IStudent{
@Override
public void action() {
System.out.println("Student action");
}
}
基于jdk的动态代理 该动态代理一定要实现InvocationHandler
/**
* @author jiaqing.xu@hand-china.com
* @version 1.0
* @name
* @description 基于jdk的动态代理 该动态代理一定要实现InvocationHandler
* @date 2018/7/23
*/
public class JavaProxy implements InvocationHandler {
private Object target; /**
* 绑定委托对象并返回一个代理类
*
* @param target
* @return
*/
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); // 要绑定接口
} @Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result;
//在这里可以做拦截前的操作
System.out.println("【java代理】调用实际方法前");
// 执行方法
result = method.invoke(target, args);
//在这里可以做拦截后的操作
System.out.println("【java代理】调用实际方法后");
return result;
}
}
/**
* @author jiaqing.xu@hand-china.com
* @version 1.0
* @name
* @description
* @date 2018/7/23
*/
public class TestProxy {
public static void main(String[] args) {
//创建代理对象
JavaProxy proxy = new JavaProxy();
//绑定接口对象
IStudent student = (IStudent) proxy.bind(new StudentImpl());
//调用接口方法
student.action();
}
}
三、基于cglib的动态代理
可以对任何的普通类进行代理
/**
* @author jiaqing.xu@hand-china.com
* @version 1.0
* @name
* @description 一个普通类
* @date 2018/7/23
*/
public class StudentImpl {
public void action() {
System.out.println("[Student]实际方法。。。");
}
}
代理类要去实现MethosInterceptor接口:
/**
* @author jiaqing.xu@hand-china.com
* @version 1.0
* @name
* @description
* @date 2018/7/23
*/
public class CgLibProxy implements MethodInterceptor {
private Object target; /**
* 创建代理对象
*
* @param target
* @return
*/
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
} // 回调方法 拦截方法 在调用具体的业务逻辑前和后 进行其他的相关处理
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("[cglib代理]调用实际方法前");
proxy.invokeSuper(obj, args);
System.out.println("[cglib代理]调用实际方法后");
return null;
}
}
/**
* @author jiaqing.xu@hand-china.com
* @version 1.0
* @name
* @description
* @date 2018/7/23
*/
public class TestProxy {
public static void main(String[] args) {
CgLibProxy cglib = new CgLibProxy();
StudentImpl student = (StudentImpl) cglib.getInstance(new StudentImpl());
student.action();
}
}
Java静态代理&动态代理&Cglib代理详解的更多相关文章
- 静态代理和动态代理(jdk/cglib)详解
1.静态代理模式 代理模式上,基本上有Subject角色,RealSubject角色,Proxy角色.其中:Subject角色负责定义RealSubject和Proxy角色应该实现的接口:RealSu ...
- 转 Java虚拟机5:Java垃圾回收(GC)机制详解
转 Java虚拟机5:Java垃圾回收(GC)机制详解 Java虚拟机5:Java垃圾回收(GC)机制详解 哪些内存需要回收? 哪些内存需要回收是垃圾回收机制第一个要考虑的问题,所谓“要回收的垃圾”无 ...
- [ 转载 ] Java开发中的23种设计模式详解(转)
Java开发中的23种设计模式详解(转) 设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类 ...
- Java基础13:反射与注解详解
Java基础13:反射与注解详解 什么是反射? 反射(Reflection)是Java 程序开发语言的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性. Orac ...
- Java工程师 基础+实战 完整路线图(详解版)
Java工程师 基础+实战 完整路线图(详解版) Java 基础 Java 是一门纯粹的面向对象的编程语言,所以除了基础语法之外,必须得弄懂它的 oop 特性:封装.继承.多态.此外还有泛型.反射 ...
- Java多线程编程中Future模式的详解
Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...
- Java进阶(三十二) HttpClient使用详解
Java进阶(三十二) HttpClient使用详解 Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们 ...
- Java多线程编程中Future模式的详解<转>
Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...
- Java中堆内存和栈内存详解2
Java中堆内存和栈内存详解 Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,ja ...
- Java web 入门知识 及HTTP协议详解
Java web 入门知识 及HTTP协议详解 WEB入门 WEB,在英语中web即表示网页的意思,它用于表示Internet主机上供外界访问的资源. Internet上供外界访问的Web资 ...
随机推荐
- (二)快速搭建 ASP.net core Web 应用
目录 1. 新建项目并上传Github 2. 关联Jenkins实现持续集成 3. 已经磨好枪了,开始写代码 1. 新建项目并上传Github 新建 ASP.NET Core Web 应用程序,勾选“ ...
- 正则表达式-Regex详解
1.什么是正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑.给定一个正 ...
- 【Leetcode】【简单】【217. 存在重复元素】【JavaScript】
题目描述 217. 存在重复元素 给定一个整数数组,判断是否存在重复元素. 如果任何值在数组中出现至少两次,函数返回 true.如果数组中每个元素都不相同,则返回 false. 示例 1: 输入: [ ...
- Enum与最佳単例设计
1 枚举基础 自定义一个枚举类很简单, 不过类型关键字是 enum, 不是 class, 也不是 interface.public enum Action { UP, DOWN, LEFT, RIGH ...
- c#搭建jenkins自动构建环境
这边我使用的是参数化构建过程,文笔比较差劲,就直接上干货了 1.定义构造参数 2.设置jenkins工作空间目录,在此定义了版本号和工作目录构建参数 3.配置svn 4.构建触发器,用于轮询查看svn ...
- 淘淘购物系统 (Python)
#首页def tao_first(): t1 = '欢迎进入淘淘购物'.center(110) print(t1) print('~' * 130) t2 = '注册'.center(20) prin ...
- 【Spring】 IOC Base
一.关于容器 1. ApplicationContext和BeanFactory 2. 配置文件 XML方式 Java-configuration 方式 @Configuration 3. 初始化容器 ...
- css绝对定位
绝对定位是我们在使用css时经常使用到的一种布局方式,下面说一下什么是绝对定位. 绝对定位使用position:absolute来定义,首先,要理解的是使用了绝对定位的元素它会脱离文档流,所谓脱离文档 ...
- IDEA中的各种快捷键
1.get.set快捷键: Alt+Insert 2.idea补全返回值快捷键 比如写了一个new User(),需要补全前面的User user ctrl+alt+V 3.idea全局搜索: Ctr ...
- FreeSql (二十一)查询返回数据
FreeSql 采用 ExpressionTree 优化读取速读,如果懂技术的你一定知道 .NETCore 技术下除了原生代码,最快就是 Emit 和 ExpressionTree. 项目在初期使用的 ...