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出来的)才 ...
随机推荐
- 【xinsir】分享一个查找文件的脚手架
program.command('find <name>').action(name => { if (name) { inquirer .prompt([ { type: 'inp ...
- python中生成器及迭代器
列表生成式 列表生成式是python内部用来创建list的一种方法,其格式形如: L = [x*8 for x in range(10)] print(L) 此时会得到结果:[0, 8, 16, 24 ...
- MYSQL5.7修改密码强度策略
---恢复内容开始--- 在MySQL5.6.6之后,ORACLE更新了mysql密码强度必须要使用大小写数字符号来设置密码,但是有时候这样还是很不方便的.所以记录一篇如何修改mysql密码强度的博文 ...
- NOIP模拟 13
我终于又厚颜无耻地赖着没走 ...... T1 矩阵游戏 用了30hmin找规律,然后发现貌似具有交换律,然后发现貌似有通项公式,然后发现貌似每次操作对通项的影响是相同的,然后发现貌似跟N没啥关系.. ...
- spring session源码解析
模块划分 core部分代码 存储实现部分部分: jdbc实现 具体存储的实现类 例如:org.springframework.session.jdbc.JdbcOperationsSessionRep ...
- Jenkins发送测试报告
邮件全局配置 邮件插件:Email Extension Plugin 功能:发送邮件 邮件全局配置:jenkins--系统管理--系统配置:截图: 配置说明: 系统管理员邮件地址:必须配置,配置后邮件 ...
- 分类算法之逻辑回归(Logistic Regression
分类算法之逻辑回归(Logistic Regression) 1.二分类问题 现在有一家医院,想要对病人的病情进行分析,其中有一项就是关于良性\恶性肿瘤的判断,现在有一批数据集是关于肿瘤大小的,任务就 ...
- Box 黑科技 —— 支持手机端反编译 !Box 黑科技 —— 支持手机端反编译 !
项目地址: Box 文末扫码获取最新安装包 . 前言 有将近一个月没有更新文章了,一方面在啃 AOSP ,消化起来确实比较慢.在阅读的过程中,有时候上来就会陷入源码细节,其实这是没有必要的.刚开始更多 ...
- windows备份mysql数据库
1.编写执行文件mysql_backup.bat rem auther:ELSON ZENGrem date:20191104rem mysql backup! @echo off set mysql ...
- 前端Leader你应该知道的NPM包管理机制
npm install 命令 首先总结下npm 安装一个模块包的常用命令. /* 模块依赖会写入 dependencies 节点 */ npm install moduleName npm insta ...