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资 ...
随机推荐
- (五十三)c#Winform自定义控件-滚动文字
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...
- 日志RedisTemplate 存储
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis. ...
- Codeforces Round #511 (Div. 2)-C - Enlarge GCD (素数筛)
传送门:http://codeforces.com/contest/1047/problem/C 题意: 给定n个数,问最少要去掉几个数,使得剩下的数gcd 大于原来n个数的gcd值. 思路: 自己一 ...
- lightoj 1105 - Fi Binary Number(dp+思维(斐波那契))
题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1105 题解:这题你会巧妙的发现 1-(1),2-(10),3-(100),5- ...
- 百度之星资格赛 调查问卷 bitset模板(直接将字符串转化成二进制数组并可以计算出十进制值)
Problem Description 度度熊为了完成毕业论文,需要收集一些数据来支撑他的论据,于是设计了一份包含 mm 个问题的调查问卷,每个问题只有 'A' 和 'B' 两种选项. 将问卷散发出去 ...
- JOBDU 1027 欧拉回路
题目1027:欧拉回路 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:3620 解决:1847 题目描述: 欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条 ...
- CF980B Marlin 构造 思维 二十四
Marlin time limit per test 1 second memory limit per test 256 megabytes input standard input output ...
- CF990C Bracket Sequences Concatenation Problem 思维 第五道 括号经典处理题目
Bracket Sequences Concatenation Problem time limit per test 2 seconds memory limit per test 256 meg ...
- gulp的介绍和手动安装
gulp, 前端自动化工具, 文件操作, 项目上线之前,将碎片文件合并,将ES6转成ES5,文件压缩,快速搭建服务器... gulp基于node环境 gulp就是node的一个非内置的小模块 gulp ...
- GNU大型项目构建和覆盖率生成(第一篇)
目录 0. 序言 1. 项目描述 2. 项目构建 2.1 编译规则 2.2 构建过程 3. 覆盖率分析 0. 序言 在开始正文之前,请允许我先说明一下本文的目的和写作的动机,好让读者不惑. 我们知道, ...