静态代理

抽象主题角色:声明真实主题和代理主题的共同接口。

代理主题角色:代理主题内部含有对真实主题的引用,从而在任何时候操作真实主题对象;代理主题提供一个与真实主题相同的接口,以便在任何时候都可以代替真实主题。代理角色通常在将客户端调用传递给真实的主题之前或之后,都要执行某个操作,而不是单纯的传递调用。

真实主题角色:定义代理角色所代表的的真实对象。

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代理的更多相关文章

  1. Java设计模式系列之动态代理模式(转载)

    代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public interface Sub ...

  2. java设计模式中的动态代理

    Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩 ...

  3. 代理模式详解:静态代理、JDK动态代理与Cglib动态代理

    代理模式简介分类 概念 ​ 代理,是为了在不修改目标对象的基础上,增强目标方法的业务逻辑. ​ 客户类需要执行的是目标对象的目标方法,但是真正执行的是代理对象的代理方法,客户类对目标对象的访问是通过代 ...

  4. 黑马程序员:Java基础总结----静态代理模式&动态代理

    黑马程序员:Java基础总结 静态代理模式&动态代理   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public  class  Ts {   ...

  5. java 代理模式一: 静态代理

    代理模式: 代理模式的作用:为其他对象提供一种代理以控制对 特定对象  的访问. 某种情况下,一个客户不想或者直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用:通过代理对象引用. ...

  6. 总结两种动态代理jdk代理和cglib代理

    动态代理 上篇文章讲了什么是代理模式,为什么用代理模式,从静态代理过渡到动态代理. 这里再简单总结一下 什么是代理模式,给某个对象提供一个代理对象,并由代理对象控制对于原对象的访问,即客户不直接操控原 ...

  7. java 设计模式 --委派模式

    委派模式(Delegate)原理: 类B和类A是两个互相没有任何关系的类,但是B具有和A一模一样的方法和属性:并且调用B中的方法/属性就是调用A中同名的方法和属性. B好像就是一个受A授权委托的中介, ...

  8. 3.java设计模式-建造者模式

    Java设计模式-建造者模式 在<JAVA与模式>一书中开头是这样描述建造(Builder)模式的: 建造模式是对象的创建模式.建造模式可以将一个产品的内部表象(internal repr ...

  9. Java设计模式——组合模式

    JAVA 设计模式 组合模式 用途 组合模式 (Component) 将对象组合成树形结构以表示“部分-整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有唯一性. 组合模式是一种结构型模 ...

  10. java设计模式--单列模式

    java设计模式--单列模式 单列模式定义:确保一个类只有一个实例,并提供一个全局访问点. 下面是几种实现单列模式的Demo,每个Demo都有自己的优缺点: Demo1: /** * 单列模式需要满足 ...

随机推荐

  1. 002-官网安装openstack之-安装基础服务

    安装openstack基础服务 1.控制节点安装时间同步服务(chrony) (1)时间同步大体来说有两种方式: 一种是自己搭建时间同步服务器,各个需要同步时间的节点,与其同步时间 另一种则是使用nt ...

  2. http服务读取配置文件,交叉编译

    因为是在windows上编译的代码,在linux上不可执行,所以需要交叉编译 package main import ( "flag" "gopkg.in/ini.v1& ...

  3. Github搭建简单的博客

    1)安装pelcan和markdown pip install pelican markdown --upgrade 2)创建一个文件夹用来作为博客的目录 mkdir 博客目录 3)cd到该目录下运行 ...

  4. web 介绍

    Web介绍: w3c:万维网联盟组织,用来制定web标准的机构(组织) web标准:制作网页遵循的规范 web准备规范的分类:结构标准.表现标准.行为标准. 结构:html.表示:css.行为:Jav ...

  5. proxysql 学习一 proxysql docker 运行试用

    proxysql 是一个比较强大的mysql proxy 服务,支持动态mysql 实例调整,查询重写,查询cache,监控,数据镜像,读写分离 以及ha,最近已经发布了2.0 ,很值得试用下 环境准 ...

  6. fio 文件系统io 性能测试安装使用

    备注: 使用的是yum 进行的安装,大家可以使用源码编译安装(centos 7) 安装 yum install -y fio 命令行参数 fio-2.2.8 fio [options] [job op ...

  7. virtualenvwrapper 方便的virtualenv 包装

      virtualenvwrapper 是一个方便的virtualenv 包装我们可以用来方便的管理python 的开发环境,同时 也支持对于项目的管理 安装 pip 安装 pip install v ...

  8. 分类模型的性能评价指标(Classification Model Performance Evaluation Metric)

    二分类模型的预测结果分为四种情况(正类为1,反类为0): TP(True Positive):预测为正类,且预测正确(真实为1,预测也为1) FP(False Positive):预测为正类,但预测错 ...

  9. 了解Python-白 驹 过 隙 , 忽 然 而 已

    白 驹 过 隙 , 忽 然 而 已 人 生 苦 短,我 用 Python -- Life is short , you need Python 代码量少,同一样问题 ,用不同的语言解决时,一般情况下P ...

  10. Echarts的简单入门

    5 分钟上手 ECharts 获取 ECharts 你可以通过以下几种方式获取 ECharts. 从官网下载界面选择你需要的版本下载,根据开发者功能和体积上的需求,我们提供了不同打包的下载,如果你在体 ...