Java设计模式--代理模式+动态代理+CGLib代理
静态代理
抽象主题角色:声明真实主题和代理主题的共同接口。
代理主题角色:代理主题内部含有对真实主题的引用,从而在任何时候操作真实主题对象;代理主题提供一个与真实主题相同的接口,以便在任何时候都可以代替真实主题。代理角色通常在将客户端调用传递给真实的主题之前或之后,都要执行某个操作,而不是单纯的传递调用。
真实主题角色:定义代理角色所代表的的真实对象。
UML图:
抽象主题
public interface Subject {
void request();
}
真实主题
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("真实对象的方法");
}
}
代理主题
public class ProxySubject implements Subject { private RealSubject subject; public ProxySubject() {
} @Override
public void request() {
pre();
if (subject == null){
subject = new RealSubject();
}
subject.request();
post();
} private void pre(){
System.out.println("方法执行之前");
} private void post(){
System.out.println("方法执行之后");
}
}
执行:
public static void main(String[] args) throws Exception {
ProxySubject subject = new ProxySubject();
subject.request();
}
输出:
方法执行之前
真实对象的方法
方法执行之后
动态代理
JDK自带的动态代理,实现InvocationHandler接口。
声明接口
public interface MyConnection extends AutoCloseable { void createStatement() throws Exception; @Override
void close() throws Exception;
}
真实主题
public class MyDefaultConnection implements MyConnection {
@Override
public void createStatement() throws Exception {
System.out.println("Create Statement ...");
} @Override
public void close() throws Exception {
System.out.println("Close Connection ...");
}
}
代理主题
public class MyConnectionProxy implements InvocationHandler { private MyConnection conn;
private MyConnection proxyConn; public MyConnectionProxy(MyConnection conn) {
this.conn = conn;
this.proxyConn = (MyConnection) Proxy.newProxyInstance(MyConnection.class.getClassLoader(), new Class<?>[] {MyConnection.class}, this);
} public MyConnection getConn() {
return conn;
} public MyConnection getProxyConn() {
return proxyConn;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
System.out.println("==代理方法:" + methodName);
if("close".equals(methodName)){
System.out.println("**不执行close方法");
}else{
return method.invoke(conn, args);
}
return null;
}
}
执行:
public static void main(String[] args) throws Exception {
MyConnection connection = new MyDefaultConnection();
MyConnectionProxy proxy = new MyConnectionProxy(connection);
proxy.getProxyConn().createStatement();
proxy.getProxyConn().close();
}
你会发现我的代理对象去哪里了?实际上我放在InvocationHandler的实现类里面了,这里参考的是mybatis源码的设计。
输出:
==代理方法:createStatement
Create Statement ...
==代理方法:close
**不执行close方法
CGLib
CGLib不需要接口就能实现动态代理。
CGLIB 原理:动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。它比使用java反射的JDK动态代理要快。
CGLIB 底层:使用字节码处理框架ASM,来转换字节码并生成新的类。
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.12</version>
</dependency>
需要代理的对象
public class Programmer { public void work(){
System.out.println("程序员正在敲代码...");
} public final void finalCannotOverride(){
System.out.println("final方法不能被生成的子类覆盖");
} private void privateCannotOverride(){
System.out.println("private方法不能被生成的子类覆盖");
}
}
代理类
public class ProgrammerProxy implements MethodInterceptor { // 真实对象
private Object realObject;
// 代理对象
private Object proxyObject; public ProgrammerProxy(Object realObject) {
this.realObject = realObject;
Enhancer enhancer = new Enhancer();
// 设置需要代理的对象
enhancer.setSuperclass(realObject.getClass());
// 设置代理人
enhancer.setCallback(this);
this.proxyObject = enhancer.create();
} public Programmer getProxyObject() {
return (Programmer) proxyObject;
} @Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
pre();
Object result = method.invoke(realObject, objects);
post();
return result;
} private void pre(){
System.out.println("==先吃早餐");
} private void post(){
System.out.println("==下班打卡");
}
}
执行:
public static void main(String[] args) throws Exception {
Programmer programmer = new Programmer();
ProgrammerProxy proxy = new ProgrammerProxy(programmer);
proxy.getProxyObject().finalCannotOverride();
proxy.getProxyObject().work();
}
输出:
final方法不能被生成的子类覆盖
==先吃早餐
程序员正在敲代码...
==下班打卡
Java设计模式--代理模式+动态代理+CGLib代理的更多相关文章
- Java设计模式系列之动态代理模式(转载)
代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public interface Sub ...
- java设计模式中的动态代理
Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩 ...
- 代理模式详解:静态代理、JDK动态代理与Cglib动态代理
代理模式简介分类 概念 代理,是为了在不修改目标对象的基础上,增强目标方法的业务逻辑. 客户类需要执行的是目标对象的目标方法,但是真正执行的是代理对象的代理方法,客户类对目标对象的访问是通过代 ...
- 黑马程序员:Java基础总结----静态代理模式&动态代理
黑马程序员:Java基础总结 静态代理模式&动态代理 ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public class Ts { ...
- java 代理模式一: 静态代理
代理模式: 代理模式的作用:为其他对象提供一种代理以控制对 特定对象 的访问. 某种情况下,一个客户不想或者直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用:通过代理对象引用. ...
- 总结两种动态代理jdk代理和cglib代理
动态代理 上篇文章讲了什么是代理模式,为什么用代理模式,从静态代理过渡到动态代理. 这里再简单总结一下 什么是代理模式,给某个对象提供一个代理对象,并由代理对象控制对于原对象的访问,即客户不直接操控原 ...
- java 设计模式 --委派模式
委派模式(Delegate)原理: 类B和类A是两个互相没有任何关系的类,但是B具有和A一模一样的方法和属性:并且调用B中的方法/属性就是调用A中同名的方法和属性. B好像就是一个受A授权委托的中介, ...
- 3.java设计模式-建造者模式
Java设计模式-建造者模式 在<JAVA与模式>一书中开头是这样描述建造(Builder)模式的: 建造模式是对象的创建模式.建造模式可以将一个产品的内部表象(internal repr ...
- Java设计模式——组合模式
JAVA 设计模式 组合模式 用途 组合模式 (Component) 将对象组合成树形结构以表示“部分-整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有唯一性. 组合模式是一种结构型模 ...
- java设计模式--单列模式
java设计模式--单列模式 单列模式定义:确保一个类只有一个实例,并提供一个全局访问点. 下面是几种实现单列模式的Demo,每个Demo都有自己的优缺点: Demo1: /** * 单列模式需要满足 ...
随机推荐
- 爬虫 - 请求库之selenium
介绍 官方文档 selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题 selenium本质是通过驱动浏览器,完全模拟浏览器的 ...
- DockerToolbox安装docker - Windows 10家庭版
由于本机使用的是win10家庭版操作系统,无法直接Docker for Windows安装,因此只好使用Docker Toolbox.在此记录一下过程,以供参考. 下载 因为toolbox安装包的官网 ...
- Python爬虫进阶 | 异步协程
一.背景 之前爬虫使用的是requests+多线程/多进程,后来随着前几天的深入了解,才发现,对于爬虫来说,真正的瓶颈并不是CPU的处理速度,而是对于网页抓取时候的往返时间,因为如果采用request ...
- 2-ESP8266 SDK开发基础入门篇--非RTOS版与RTOS版
https://www.cnblogs.com/yangfengwu/p/11071580.html 所有的源码 https://gitee.com/yang456/Learn8266SDKDevel ...
- Awesome Go精选的Go框架,库和软件的精选清单.A curated list of awesome Go frameworks, libraries and software
Awesome Go financial support to Awesome Go A curated list of awesome Go frameworks, libraries a ...
- 最大の和(洛谷 AT2412)
题意 读入n个整数的数列a1,a2,…,an和正整数k(1<=k<=n),请输出连续排列的k个整数的和的最大值 输入 第一行是正整数n(1<=n<=100000)和正整数k(1 ...
- git-中文乱码
Windows系统的Git默认是不支持中文显示的,需要进行一系列的设置才能避免乱码的出现,下面总结如何配置Git使其支持中文显示. Git bash options UTF-8编码配置 1.首先进入g ...
- OpenFOAM——运动和静止的同心圆柱之间的流动(库埃特流)
本算例来自<ANSYS Fluid Dynamics Verification Manual>中的VMFL001: Flow Between Rotating and Stationary ...
- Net core学习系列(二)——Net Core项目文件简介
一. ASP.NET Core 项目文件夹解读 ASP.NET Core 1.0 发布以来,相较于传统项目编码发布的行为,新项目中的操作已经有了很大的变化,如解析依赖,选择运行平台和Runtime等等 ...
- PHP系列 | PHP5.6 安装 endroid/qr-code 遇到的问题
官方库地址:https://packagist.org/packages/endroid/qr-code PHP5.6 的最高版本为:2.5.1 通过composer安装 composer requi ...