一、静态代理模式
静态代理,使用继承的方式实现自己新增的服务
这种模式可以实现帮助被代理者完成一些前期的准备工作和后期的善后工作,但是核心的业务逻辑仍然是由被代理者完成。
在某些情况下,一个客户不想或者不能直接引用一个对象,此时可以通过一个代理的第三者间接引用,。起到中介的作用,并且可以通过代理对象去掉客户不能看到的内容和服务或额外服务。

代理是一个对象,代理对象为其他对象提供一种代理,以控制对这个对象的访问,代理对象起到中介作用,可以去掉或者增加额外的服务。
如:火车票代售点就是火车站售票处的一个代理对象,可通过访问代售点进行业务处理。
二,静态代理的2种实现方式:继承和聚合
静态代理中的代理和被代理对象在代理之前关系是确定的。它们都实现了相同的接口或者继承相同的抽象类。
下面的例子分别讲述了所有的类实现同一个接口,类对象之间是如何代理的。

案例代码实现:
1.定义一个接口类Moveable.java
package com.sjms.test.proxy.interfaces;

public interface Moveable {
void move();
}

2.定义一个实体类Car.java 并实现以上接口。
package com.sjms.test.proxy.impl;

import com.sjms.test.proxy.interfaces.Moveable;

public class Car implements Moveable {

@Override
public void move() {
try {
System.out.println("开始喽");
Thread.sleep(1000L);

} catch (Exception e) {
e.printStackTrace();
}
}

}

3.定义一个代理类Car2.java(此类,即实现了父类方法,又实现了新增的业务)
package com.sjms.test.proxy.impl;

public class Car2 extends Car {
public void move() {//实现自身方法
Long startTime = System.currentTimeMillis();
System.out.println("开始开车。。。。");
super.move();//实现父类方法
Long endTime = System.currentTimeMillis();
System.out.println("已经停止。。。。,用时:"+(endTime-startTime));
}
}
4.Test.java类
package com.sjms.test.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

import com.sjms.test.proxy.handler.TimerHandler;
import com.sjms.test.proxy.impl.Car;
import com.sjms.test.proxy.impl.Car2;
import com.sjms.test.proxy.impl.Car3;
import com.sjms.test.proxy.interfaces.Moveable;

4.通过聚合构造函数方式 (通过将参数传递进来,然后我们使用传递进来的参数,调用其方法,实现静态代理)
public class Car3 implements Moveable{

private Car car;
public Car3(Car car) {
super();
this.car = car;
}

@Override
public void move() {
long starttime = System.currentTimeMillis();
System.out.println("汽车开始行驶.......");
     //通过构造方法将car传进来,然后通过car调用方法
car.move();
long endtime = System.currentTimeMillis();
System.out.println("汽车结束行驶......");
System.out.println("汽车行驶时间:"+(endtime - starttime)+"毫秒!");
}
}

public class Test {
public static void main(String[] args) {
//1.静态代理,使用继承的方式实现自己新增的服务
Moveable moveable = new Car2();
moveable.move();

//2.聚合静态代理,使用构造方法传入参数。
/*Car car = new Car();
Moveable car3 = new Car3(car);
car3.move();*/

}
}

二、使用静态代理,会让我们的代理类无限膨胀下去,所以出现了动态代理模式(JDK动态代理、CGLIB动态代理)
在代理类和被代理类之间加上一个事务处理器,将我们需要处理的具体功能放在其中进行处理。

1.JDK动态代理(InvocationHandler事务处理器,Proxy:代理类)
InvocationHandler接口中仅定义了一个方法public object invoke(Object obj,Method method,Object[] args)
第一个参数:代理类,第二个参数:被代理的方法,第三个参数:该方法的参数数组
Proxy:动态代理类,通过newProxyInstance方法返回代理类的实例,

实现步骤:
1).创建一个实现InvocationHandler接口的实现类,并实现invoke方法
2).创建被代理的类和接口(Car和Moveable 在上面的案例中已经构建)
3).动态创建一个代理类(Proxy.newProxyInstance)package com.sjms.test.proxy.handler;
TimerHandler.java

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class TimerHandler implements InvocationHandler{
private Object target;
public TimerHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] param)
throws Throwable {
Long startTime = System.currentTimeMillis();
System.out.println("汽车开始行使了...");
method.invoke(target);
Long entTime = System.currentTimeMillis();
System.out.println("汽车结束行驶......");
System.out.println("汽车行驶时间:"+(entTime - startTime)+"毫秒!");
return null;
}

}

Test.java 构造代理类,实现具体的代理类

package com.sjms.test.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

import com.sjms.test.proxy.handler.TimerHandler;
import com.sjms.test.proxy.impl.Car;
import com.sjms.test.proxy.impl.Car2;
import com.sjms.test.proxy.impl.Car3;
import com.sjms.test.proxy.interfaces.Moveable;

public class Test {
public static void main(String[] args) {
//1.静态代理,使用继承的方式实现自己新增的服务
Moveable moveable = new Car2();
moveable.move();

//2.聚合静态代理,使用构造方法传入参数。
/*Car car = new Car();
Moveable car3 = new Car3(car);
car3.move();*/

//3.动态代理
Car carObj = new Car();//被代理的类
InvocationHandler handler = new TimerHandler(carObj);//事务处理器
//使用代理器实现
Moveable move = (Moveable)Proxy.newProxyInstance(carObj.getClass().getClassLoader(), carObj.getClass().getInterfaces(), handler);
//move 为生产的代理类
move.move();
}
}

2.cgLib的动态代理实现
由于JDK只能针对实现了接口的类做动态代理,而不能对没有实现接口的类做动态代理,所以cgLib横空出世!
CGlib是一个强大、高性能的Code生成类库,它可以在程序运行期间动态扩展类或接口,它的底层是使用java字节码操作框架ASM实现。它可以动态的操作类部方法

1) 引入cgLib 库
2)定义业务类,被代理的类没有实现任何接口(有实现接口的也可以)
package com.sjms.test.proxy.impl;

public class Car4 {
public void move() {
System.out.println("开始发车");
}
}
3)定义拦截器,在调用目标方法时,CGlib会回调MethodInterceptor 接口方法拦截,来实现你自己的代理逻辑,类似于JDK中的InvocationHandler接口。
package com.sjms.test.proxy.handler;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
* cglib 动态代理拦截器实现
* */
public class CglibDynProxyInterceptor implements MethodInterceptor{

@Override
public Object intercept(Object arg0, Method arg1, Object[] params,
MethodProxy methodProxy) throws Throwable {
if (arg1.getName().equals("move")){
System.out.println("cgLib动态代理拦截器开始,拦截方法mmove()......");
//代理类调用父类的方法
return methodProxy.invokeSuper(arg0, params);
}
return null;
}

}
4)定义动态代理工厂,生成动态代理
package com.sjms.test.proxy.factory;

import com.sjms.test.proxy.handler.CglibDynProxyInterceptor;

import net.sf.cglib.proxy.Enhancer;
//生产代理工厂

public class CglibProxyFactory {
public static Object getCarProxy(Object target){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(new CglibDynProxyInterceptor());
return enhancer.create();
}
}
5)测试
package com.sjms.test.proxy;

import com.sjms.test.proxy.factory.CglibProxyFactory;
import com.sjms.test.proxy.impl.Car4;

public class Car4CglibTest {
public static void main(String[] args){
//Cglib动态代理原理,就是通过拦截器来新增自己的增值业务
Car4 car = (Car4)CglibProxyFactory.getCarProxy(new Car4());
car.move();
}
}

ps:切面编码实际底层原理使用动态代理模式
cgLib的动态代理原理
CGLIB原理:动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。它比使用java反射的JDK动态代理要快。

CGLIB底层:使用字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。

CGLIB缺点:对于final方法,无法进行代理。

Java常见23中设计模式之【代理模式】的更多相关文章

  1. java的23中设计模式

    一.设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接 ...

  2. Java开发23中设计模式

    设计模式(Design Patterns) 设计模式是一套被反复使用,多数人知晓的,经过分类编目的,代码设计经验的总结.使用设计模式是为了可重用代码,让代码更容易被他人理解,保证代码的可靠性.毫无疑问 ...

  3. Java进阶篇设计模式之七 ----- 享元模式和代理模式

    前言 在上一篇中我们学习了结构型模式的组合模式和过滤器模式.本篇则来学习下结构型模式最后的两个模式, 享元模式和代理模式. 享元模式 简介 享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能 ...

  4. 【java设计模式】(3)---代理模式(案例解析)

    设计模式之代理模式 一.概述 1.什么是代理模式? 解释第一遍:代理模式主要由三个元素共同构成: 1)一个接口,接口中的方法是要真正去实现的. 2)被代理类,实现上述接口,这是真正去执行接口中方法的类 ...

  5. Java设计模式之七 ----- 享元模式和代理模式

    前言 在上一篇中我们学习了结构型模式的组合模式和过滤器模式.本篇则来学习下结构型模式最后的两个模式, 享元模式和代理模式. 享元模式 简介 享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能 ...

  6. [转载]Java中继承、装饰者模式和代理模式的区别

    [转载]Java中继承.装饰者模式和代理模式的区别 这是我在学Java Web时穿插学习Java设计模式的笔记 我就不转载原文了,直接指路好了: 装饰者模式和继承的区别: https://blog.c ...

  7. java的23种设计模式之建造者模式

    场景和本质 场景 本质 案例 原理 应用场景 场景和本质 场景 我们要建造一个复杂的产品.比如:神州飞船,Iphone.这个复杂的产品的创建.有这样一个问题需要处理:装配这些子组件是不是有个步骤问题? ...

  8. 菜鸟版JAVA设计模式—从买房子看代理模式

    今天学习了代理模式. 相对于适配器模式,或者说装饰器模式,代理模式理解起来更加简单. 代理这个词应该比較好理解,取代去做就是代理. 比方,我们买卖房子,那么我们会找中介,我要卖房子,可是我们没有时间去 ...

  9. 【Unity与23种设计模式】代理模式(Proxy)

    GoF中定义: "提供一个代理者位置给一个对象,好让代理者可以控制存取这个对象." 代理模式多用来优化资源的加载 当资源已经加载过时,使用原来的资源 当资源没有加载过时,开始加载 ...

随机推荐

  1. Java实现 LeetCode 565 数组嵌套(没有重复值的数组)

    565. 数组嵌套 索引从0开始长度为N的数组A,包含0到N - 1的所有整数.找到并返回最大的集合S,S[i] = {A[i], A[A[i]], A[A[A[i]]], - }且遵守以下的规则. ...

  2. DEV控件之TreeList使用

    绑定DataTable 直接设置DataSource即可,同时需要设置KeyFieldName和ParentFieldName两个属性,好处就是,无需像TreeView一样去递归节点,设置了这两个属性 ...

  3. vs2019离线下载安装包

    官方的离线安装说明-->点击打开 1.下载 vs2019引导程序 ,选择你所需的版本下载,我选择了企业版 vs_enterprise__184447765.1558180718.exe 2.设置 ...

  4. Android数据库框架-ORMLite

    参考资料 Android ORMLite 框架的入门用法 Android 快速开发系列 ORMLite 框架最佳实践 添加依赖 compile 'com.j256.ormlite:ormlite-an ...

  5. Verifying dml pool data

    数据出错 ,硬件变动 解决方案: 1.移除外接设备 2.bios还原

  6. 不需重新编译php,安装postgresql扩展(pgsql和pdo_pgsql)

    为了不重新编译php,使用phpize工具进行追加. 1.下载phpX安装包 访问php官方下载页,找到自己对应的php版本:https://secure.php.net/downloads.php ...

  7. PowerApps Component Framework PCF 部署

    PowerApps PCF 可以满足复杂的功能, 我们可以使用PCF来创建复杂的PowerApps. 这里附上微软的package code componet 教程(https://docs.micr ...

  8. Spring IOC原理补充(循环依赖、Bean作用域等)

    文章目录 前言 正文 循环依赖 什么是循环依赖? Spring是如何解决循环依赖的? 作用域实现原理以及如何自定义作用域 作用域实现原理 自定义Scope BeanPostProcessor的执行时机 ...

  9. Dubbo——服务调用过程

    文章目录 引言 服务的交互 服务降级 集群容错 服务调用 服务端接收请求 总结 引言 经过之前文章的铺垫,现在可以来分析服务的交互调用过程了. 服务的交互 服务降级 从名字上看我们不难理解MockCl ...

  10. APP——python——自动化环境搭建01

    前提:python以及pycharm安装完成. ---------------------------------------------------------------------------- ...