装饰模式:以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案;

代理模式:给一个对象提供一个代理对象,并有代理对象来控制对原有对象的引用;

装饰模式为所装饰的对象增强功能;代理模式对代理的对象施加控制,并不提供对象本身的增强功能

简而言之,装饰者是指的是自身,对功能的增强,而另一种是调用接口,实现对代理对象的控制

在Spring AOP中,主要使用了两种代理方式:jdkProxy、cjlibProxy

cjlibProxy:

package com.cjlib;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /**
* @author weining
* @date 2019/10/31 8:45
*/
public class CglibProxyExample implements MethodInterceptor { public Object getProxy(Class cls) {
//CGLIB enhancer 增强类对象
Enhancer enhancer = new Enhancer(); //设置增强类型
enhancer.setSuperclass(cls); //定义逻辑对象,要求实现当前对象实现MethodInterceptor方法
enhancer.setCallback(this); //返回代理对象
return enhancer.create();
} /**
* 代理逻辑方法
*
* @param o 代理对象
* @param method 方法
* @param objects 方法参数
* @param methodProxy 方法代理
* @return 代理逻辑返回
* @throws Throwable
*/
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("调用真是对象之前");
Object invokeSuper = methodProxy.invokeSuper(o, objects);
System.out.println("调用真是对象之后"); return invokeSuper;
}
}

  测试方法:

package com.cjlib;

import com.jdk.HelloWorld;
import com.jdk.impl.HelloWorldImpl; /**
* @author weining
* @date 2019/10/31 9:03
*/
public class testCGLIBProxy {
public static void main(String[] args) {
CglibProxyExample cglibProxyExample = new CglibProxyExample();
HelloWorld helloWorld = (HelloWorldImpl) cglibProxyExample.getProxy(HelloWorldImpl.class);
helloWorld.sayHello();
}
}

  

jdkProxy:

package com.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; /**
* @author weining
* @date 2019/10/31 8:29
* 在jdk动态代理时 必须要实现InvocationHandler接口
* 自动生成接口中的invoke方法
*/
public class JdkProxyExample implements InvocationHandler { private Object target = null; public Object bind(Object target){
this.target = target;
/*
三个属性分别是:类加载器,把生成的动态代理对象挂在哪个接口之上,定义实现方法逻辑的代理类
*/
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
} /**
* invoke可以实现代理对象
* @param proxy bind 返回的对象
* @param method 当前调度的方法
* @param args 调度方法的参数
* @return 代理的结果返回
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入代理逻辑方法");
System.out.println("在调用真实对象的服务");
Object obj=method.invoke(target,args);
System.out.println("在调用真实对象之后的服务");
return obj;
}
}

这时,创建一个HelloWorld接口:

package com.jdk;

/**
* @author weining
* @date 2019/10/31 8:27
*/
public interface HelloWorld {
public void sayHello();
}

创建接口的实现类:

package com.jdk.impl;

import com.jdk.HelloWorld;

/**
* @author weining
* @date 2019/10/31 8:27
*/
public class HelloWorldImpl implements HelloWorld {
public void sayHello() {
System.out.println("Hello,World!");
}
}

最后调用测试方法:

package com.jdk;

import com.jdk.impl.HelloWorldImpl;

/**
* @author weining
* @date 2019/10/31 8:40
*/
public class test {
public static void main(String[] args) {
JdkProxyExample jdkProxyExample = new JdkProxyExample(); HelloWorld proxy = (HelloWorld) jdkProxyExample.bind(new HelloWorldImpl());
proxy.sayHello(); }
}

两者的区别

1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类。

2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,

并覆盖其中方法实现增强,但是因为采用的是继承,所以该类或方法最好不要声明成final,

对于final类或方法,是无法继承的。

装饰者模式:

//装饰器模式
public class Decorator implements Component{
private Component component;
public Decorator(Component component){
this.component = component
}
public void operation(){
….
component.operation();
….
}
}
//装饰器的客户
public class Client{
public static void main(String[] args){
//客户指定了装饰者需要装饰的是哪一个类
Component component = new Decorator(new ConcreteComponent());

}
}

Java中代理和装饰者模式的区别的更多相关文章

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

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

  2. JAVA设计模式之【装饰者模式】

    JAVA设计模式之[装饰者模式] 装饰模式 对新房进行装修并没有改变房屋的本质,但它可以让房子变得更漂亮.更温馨.更实用. 在软件设计中,对已有对象(新房)的功能进行扩展(装修). 把通用功能封装在装 ...

  3. Java中public,private,protected,和默认的区别

    Java中public,private,protected,和默认的区别 1.private修饰词,表示成员是私有的,只有自身可以访问: 2.protected,表示受保护权限,体现在继承,即子类可以 ...

  4. 【Java学习笔记之二十九】Java中的"equals"和"=="的用法及区别

    Java中的"equals"和"=="的用法及区别 在初学Java时,可能会经常碰到下面的代码: String str1 = new String(" ...

  5. java中public与private还有protect的区别

    java中public与private还有protect的区别 总是忘记.

  6. Java中的基本类型和引用类型变量的区别

    Java中的基本类型和引用类型变量的区别   学了一年多,说实话你要我说这些东西我是真说不出来是啥意思     基本类型: 基本类型自然不用说了,它的值就是一个数字,一个字符或一个布尔值. 引用类型: ...

  7. JAVA中局部变量 和 成员变量有哪些区别

    JAVA中局部变量 和 成员变量有哪些区别 1.定义的位置不一样<重点>***局部变量:在方法的内部成员变量:在方法的外部,直接写在类当中 2.作用范围不一样<重点>***局部 ...

  8. java 中,for、for-each、iterator 区别

    java 中,for.for-each.iterator 区别: 无论是在数组中还是在集合中,for-Each加强型for循环都是它们各自的普通for循环的一种"简写方式",即两者 ...

  9. java中String new和直接赋值的区别

        Java中String new和直接赋值的区别     对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才 ...

随机推荐

  1. SAP Web Service简介与配置方法

    [版权声明]本文为博主原创文章,转载请在明显位置注明出处. 一. SAP Web Service简介 二. SAP Web Service配置准备工作 1. 通过RZ10配置服务器名称和其他参数 2. ...

  2. 使用“反向传播”迭代法求解y=√10

    X=√10,求X,也就是求Y=10 =X2 , X是多少. *重要的思想是,如何转化为可迭代求解的算法问题. *解数学问题,第一时间画图,求导,“直线化”. Y = X2 假如已知Y = 10 ,要求 ...

  3. WPF项目设计规则

    关于WPF应用程序的设计: 项目构成,自上而下: 1. 前端的WPF应用程序项目. 2. 业务逻辑的类库项目. 3. 映射到数据库各个表的Model型类库,(数据库操作接口定义). 4. 其他工具型类 ...

  4. UiPath之Word转换为PDF

    前几天在手机上看到其他的文章,里面提到如何将Word转换为PDf,在UiPath的ManagePackage中,下载一个WordToPDF的包, 我按照上面的方法试着做了一下,但是在转换的时候很不稳定 ...

  5. php PDO getlastsql写法

    php PDO getlastsql写法有些时候 运行失败需要查看 sql语句 原型有没有语法错误 这个时候就用 下面的函数就是把问号替换成 值 就可以看到原型了<pre>function ...

  6. Linux之ant安装部署

    接下来呢,就开始ant的部署,具体分为如下几个步骤: 1. 获取介质: 在apache的官网中直接下载,下载地址为:http://ant.apache.org/ 下载需要的版本即可: 2. 复制到us ...

  7. Python字符串类型判断错误

    Python里面常用的字符串类型有str和unicode,如果要判断一个对象的类型,最好用basestring,否则可能会判断错误: str1 = "hello" str2 = u ...

  8. 领扣(LeetCode)两个数组的交集II 个人题解

    给定两个数组,编写一个函数来计算它们的交集. 示例 1: 输入: nums1 = [1,2,2,1], nums2 = [2,2] 输出: [2,2] 示例 2: 输入: nums1 = [4,9,5 ...

  9. python:正则1

    鱼c(扩展阅读): Python3 如何优雅地使用正则表达式(详解一) Python3 如何优雅地使用正则表达式(详解二) Python3 如何优雅地使用正则表达式(详解三) Python3 如何优雅 ...

  10. jsp页面使用EL表达式 使用Jstl标签库中的标签,需要引入jstl.jar和standard.jar

    spring boot 中使用jstl 首先在pom中加入 <dependency> <groupId>jstl</groupId> <artifactId& ...