代理模式

代理(Proxy)是一种设计模式,提供了间接对目标对象进行访问的方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的功能上,增加额外的功能补充,即扩展目标对象的功能.

这就符合了设计模式的开闭原则,即在对既有代码不改动的情况下进行功能的扩展。

举个例子来说明代理的作用:明星与经纪人之间就是被代理和代理的关系,明星出演活动的时候,明星就是一个目标对象,他只要负责活动中的节目,而其他琐碎的事情就交给他的代理人(经纪人)

来解决.这就是代理思想在现实中的一个例子。

静态代理

在使用静态代理时,被代理对象与代理对象需要一起实现相同的接口或者是继承相同父类,因此要定义一个接口或抽象类.

代码案例:

// 接口
interface IStar {
void sing();
} // 真实对象
class LDHStar implements IStar {
@Override
public void sing() {
System.out.println("刘德华唱歌");
} } // 代理类需要有真实对象的控制权 (引用)
class ProxyManger implements IStar { // 真实对象的引用
private IStar star; public ProxyManger() {
super();
} public ProxyManger(IStar star) {
super();
this.star = star;
} @Override
public void sing() {
      System.out.println("唱歌前准备");
        star.sing();
       System.out.println("善后工作"); }
}
class Test{
public static void main(String[] args) {
// 创建明星对象
IStar ldh = new LDHStar();
ProxyManger proxy = new ProxyManger(ldh);
proxy.sing();
}
}

静态代理总结:
优点:可以做到在不修改目标对象的功能前提下,对目标功能扩展.
缺点:

  因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.

而动态代理方式可以解决上面的问题

动态代理

动态代理的主要特点就是能够在程序运行时JVM才为被代理对象生成代理对象。

常说的动态代理也叫做JDK代理也是一种接口代理,JDK中生成代理对象的代理类就是Proxy,所在包是java.lang.reflect

//目标类接口
interface IDog{
void run();
}
//目标类
class GunDog implements IDog{ @Override
public void run() {
System.out.println("猎狗在跑");
}
}
class DogUtils{
public static void method1() {
System.out.println("增强方式一");
} public static void method2() {
System.out.println("增强方式二");
}
}
class MyInvocationHandle implements InvocationHandler{
private Object target;
public void setTarget(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
DogUtils.method1();
method.invoke(target, args);
DogUtils.method2();
return null;
}
}
//生产代理对象的工厂
class MyProxyFactory{
public static Object getProxy(Object target) {
MyInvocationHandle handle = new MyInvocationHandle();
handle.setTarget(target);
Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handle);
return proxy;
}
}
public class ProxyDemo {
public static void main(String[] args) {
IDog dog = new GunDog();
IDog proxy =(IDog) MyProxyFactory.getProxy(dog);
proxy.run();
} }

总结:

代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能使用动态代理,因此这也算是这种方式的缺陷。

Cglib代理

上面的静态代理和动态代理模式有个相同点就是都要求目标对象是实现一个接口的对象,然而并不是任何对象都会实现一个接口,也存在没有实现任何的接口的对象,

这时就可以使用继承目标类以目标对象子类的方式实现代理,这种方法就叫做:Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展.

使用JDK动态代理有一个限制,就是被代理的对象必须实现一个或多个接口,若想代理没有实现接口的类,就需要使用Cglib实现.

由于Cglib是第三方提供的所以使用的时候需要导入相关的jar包,有两个包如图:

代码案例:

public class CglibProxy {

    public static void main(String[] args) {

        int[] arr = new int[100000];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * 1000);
}
//实例化一个增强器,也就是cglib中的一个class generator
Enhancer enhancer = new Enhancer();
//设置目标类
enhancer.setSuperclass(ArraySort2.class);
//设置拦截对象,这里直接使用匿名内部类写法
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object object , Method method, Object[] args, MethodProxy proxy) throws Throwable {
String sortName = method.getName();
switch (sortName) {
case "bubbleSort":
sortName = "冒泡排序";
break;
case "selectSort":
sortName = "选择排序";
break;
case "quickSort":
sortName = "快速排序";
break;
default:
break;
}
long start = System.currentTimeMillis();
//此处一定要使用proxy的invokeSuper方法来调用目标类的方法
proxy.invokeSuper(object, args);
long end = System.currentTimeMillis();
System.out.println("本次" + sortName + "的执行时间为: " + (end -start) + "ms");
return null;
} });
//生成代理类并返回一个实例
ArraySort2 arraySort = (ArraySort2) enhancer.create();
arraySort.bubbleSort(arr);
arraySort.selectSort(arr);
arraySort.quickSort(arr);
} }
class ArraySort2{
public void quickSort(int[] arr) {
Arrays.sort(arr);
}
public void selectSort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = i+1; j < arr.length; j++) {
if (arr[i] > arr[j]) {
int temp = 0;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
public void bubbleSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = 0;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
}

总结:

在Spring的AOP编程中:

如果加入容器的目标对象有实现接口,用JDK代理

如果目标对象没有实现接口,用Cglib代理。

Java中三种代理模式的更多相关文章

  1. Java的三种代理模式

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

  2. Java的三种代理模式简述

    本文着重讲述三种代理模式在java代码中如何写出,为保证文章的针对性,暂且不讨论底层实现原理,具体的原理将在下一篇博文中讲述. 代理模式是什么 代理模式是一种设计模式,简单说即是在不改变源码的情况下, ...

  3. 理解java的三种代理模式

    代理模式是什么 代理模式是一种设计模式,简单说即是在不改变源码的情况下,实现对目标对象的功能扩展. 比如有个歌手对象叫Singer,这个对象有一个唱歌方法叫sing(). 1 public class ...

  4. Java的三种代理模式(Spring动态代理对象)

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

  5. Java的三种代理模式&完整源码分析

    Java的三种代理模式&完整源码分析 参考资料: 博客园-Java的三种代理模式 简书-JDK动态代理-超详细源码分析 [博客园-WeakCache缓存的实现机制](https://www.c ...

  6. 转!!Java的三种代理模式

    转自 http://www.cnblogs.com/cenyu/p/6289209.html 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象 ...

  7. 秒懂 Java 的三种代理模式

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

  8. Java的三种代理模式(Proxy,CGLib)

    1.静态代理,这种不用说最不靠谱.每个类一个代理,代码量很大. 2.JDK代理.使用java.lang.reflect.Proxy进行代理,但是被代理的类必须要实现接口. 3.Cglib代理.不用实现 ...

  9. Java的三种代理模式:静态代理/JDK动态代理/Cglib动态代理

    1.静态代理:需要定义接口或者父类,目标对象与代理对象均实现同一接口或继承同一父类. 2.JDK动态代理:需要目标对象实现一个接口,通过动态反射的机制,生成代理对象,实现同一个接口 3.Cglib动态 ...

随机推荐

  1. Educational Codeforces Round 62 Div. 2

    突然发现上一场edu忘记写了( A:签到. #include<iostream> #include<cstdio> #include<cmath> #include ...

  2. CENTOS手动安装修复python ,YUM CENTOS手动安装修复YUM

    CENTOS手动安装修复YUM  2019年3月8日  杨宇 Comments 0 Comment 目录 [hide] 一.问题场景 二.手动修复 2.1 下载 rpm 包 2.2 安装 rpm 包 ...

  3. IAR使用跳转功能时不正常的情况

    @2019-04-12 [小记] [使用环境]IAR-Arm8.30.1 [验证] 均为实测 1. 出现如下图这种情况应该是工程所在路径太深导致 2. 如果不弹出上图警告,但还是不跳转应该是工程编译信 ...

  4. yii2在控制器中调用另一个控制器方法

    Yii::$app->runAction(控制器/方法名);

  5. css解决图片拉伸问题

    在实际场景中,我们经常会遇到图片大小固定的需求,但是由于原始图片大小,比例不一样,不同图片以相同的大小展示会参差不齐.解决方法就是object-fit或者background-size属性.他们的区别 ...

  6. vue 中的通过搜索框进行数据过滤的过程

    <template> <div> <input type="text" v-model="searchId" placeholde ...

  7. 第五周java学习总结

    学号 20175206<Java程序设计>第五周学习总结 教材学习内容总结 6.1 接口 为了克服Java单继承的缺点,Java使用了接口,一个类可以实现多个接口. 使用关键字interf ...

  8. 关于rocketmq的配置启动

    #集群名称brokerClusterName=rocket-nameserver#broker-a,注意其它两个分别为broker-b和broker-cbrokerName=broker-a#brok ...

  9. IDEA 导入 Tomcat9 源码

    源码下载(Source Code Distributions)地址:https://tomcat.apache.org/download-90.cgi tomcat 和 servlet 以及 jdk ...

  10. PMP知识点(五)——配置管理

    配置控制重点关注可交付成果及各个过程的技术规范,而变更控制则着眼于识别.记录.批准或否决对项目文件,可交付成果或基准的变更. 包括在实施整体变更控制过程中的部分配置管理活动有: 1.配置识别. 识别与 ...