Java中代理和装饰者模式的区别
装饰模式:以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案;
代理模式:给一个对象提供一个代理对象,并有代理对象来控制对原有对象的引用;
装饰模式为所装饰的对象增强功能;代理模式对代理的对象施加控制,并不提供对象本身的增强功能
简而言之,装饰者是指的是自身,对功能的增强,而另一种是调用接口,实现对代理对象的控制
在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中代理和装饰者模式的区别的更多相关文章
- [转载]Java中继承、装饰者模式和代理模式的区别
[转载]Java中继承.装饰者模式和代理模式的区别 这是我在学Java Web时穿插学习Java设计模式的笔记 我就不转载原文了,直接指路好了: 装饰者模式和继承的区别: https://blog.c ...
- JAVA设计模式之【装饰者模式】
JAVA设计模式之[装饰者模式] 装饰模式 对新房进行装修并没有改变房屋的本质,但它可以让房子变得更漂亮.更温馨.更实用. 在软件设计中,对已有对象(新房)的功能进行扩展(装修). 把通用功能封装在装 ...
- Java中public,private,protected,和默认的区别
Java中public,private,protected,和默认的区别 1.private修饰词,表示成员是私有的,只有自身可以访问: 2.protected,表示受保护权限,体现在继承,即子类可以 ...
- 【Java学习笔记之二十九】Java中的"equals"和"=="的用法及区别
Java中的"equals"和"=="的用法及区别 在初学Java时,可能会经常碰到下面的代码: String str1 = new String(" ...
- java中public与private还有protect的区别
java中public与private还有protect的区别 总是忘记.
- Java中的基本类型和引用类型变量的区别
Java中的基本类型和引用类型变量的区别 学了一年多,说实话你要我说这些东西我是真说不出来是啥意思 基本类型: 基本类型自然不用说了,它的值就是一个数字,一个字符或一个布尔值. 引用类型: ...
- JAVA中局部变量 和 成员变量有哪些区别
JAVA中局部变量 和 成员变量有哪些区别 1.定义的位置不一样<重点>***局部变量:在方法的内部成员变量:在方法的外部,直接写在类当中 2.作用范围不一样<重点>***局部 ...
- java 中,for、for-each、iterator 区别
java 中,for.for-each.iterator 区别: 无论是在数组中还是在集合中,for-Each加强型for循环都是它们各自的普通for循环的一种"简写方式",即两者 ...
- java中String new和直接赋值的区别
Java中String new和直接赋值的区别 对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才 ...
随机推荐
- 小白学 Python(15):基础数据结构(集合)(下)
人生苦短,我选Python 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 小白学 Python(4):变 ...
- PHP获取当前时间
PHP获取系统当前时间,有date()可以使用. 但date()当前系统时间是格林威治时间,比我们所在的时区晚了整整8个小时.以前处理这个问题时,只是简单的把获取的当前系统的时间戳加上8个小时的时间, ...
- 记一次C#调用C++踩过的坑
一般来说,C#调用C++生产的dll,如下: C++的项目要设置为"导出dll的项目",而且导出的函数,一般为: extern "C" __declspec(d ...
- LVS DR模式实践
client:192.168.4.10/24 proxy:192.168.4.5/24 VIP: 192.168.4.15/24 web1:192.168.4.100/24 VIP:192.168 ...
- [07/18NOIP模拟测试5]超级树
鬼能想到的dp定义:dp[i][j]表示在一棵i级超级树中,有j条路径同时存在且这j条路径没有公共点时,可能的情况数 刚开始我也没看懂,所以举个例子 如一个2级的超级树,父节点为1,左右儿子为2,3 ...
- NOIP模拟测试9
又考崩了咕咕咕... T1:随 好题标记 前置芝士: 原根:质数P的原根g满足1<=rt<P,且rt的1次方,2次方…(P-1)次方在模P意义下可以取遍1到(P-1)的所有整数. ...
- sshd服务以及基于口令的远程登陆
ssh用为客户端,主要进行服务器端的连接:sshd用为服务器端 几个常用的命令: systemctl ##服务控制命令 systemctl start sshd ## ...
- HtmlSpanner 使用小结 -- 安卓解析html
如何利用 HtmlSpanner解析 HTML格式 的字符串: 1. GitHub 下载HtmlSpanner项目 https://github.com/NightWhistler/HtmlSpann ...
- phpexcel导出数字带E的解决方法
phpexcel导出数字带E的解决方法 excel之所以带E 是因为按照数字格式来显示了(数字过长的时候) 数字左边或者右边加空格就变成字符串了 那么excel就会按照字符串格式来显示了 就不会带E了
- P中值选址问题的整数规划求解
P中值选址问题的整数规划求解 一 .P-中值问题 p-中值选址问题是一个常见的选址问题. 问题是给定I个需求结点和J个待选设施地点, 要求选择p个地点建立设施, 使得运输成本最低. 下面是个英文的问题 ...