2022年9月9号Sprin框架的学习(课时七)Aop项内容设计23设计模式中的静态代理模式而在SpringAop中实现的时动态代理模式
第一部分 了解Java23模式的基本概念从下面的概念去理解扩展知识
1 什么是设计模式:
设计模式(Design Pattern)是前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、
可维护性、可读性、稳健性以及安全性的解决方案。
1995 年,GoF (Gang of Four,四人组/四人帮)合作出版了《设计模式:可复用面向对象软件的基础》一书,
共收录了23 种设计模式,从此树立了软件设计模式领域的里程碑,人称.「GoF设计模式」
2 学习设计模式的意义:
设计模式的本质是面向对象设计原则的实际运用, 是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解。
正确使用设计模式具有以下优点:
可以提高程序员的思维能力、编程能力和设计能力。
使程序设计更加标准化、 代码编制更加工程化,使软件开发效率大大提高,从而缩短软件的开发周期。
使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。
个人总结 增强自己编码的思维能力,以另外的一种思维解决生活中的问题。
3 GoF23设计模式指哪些:每种模式体现每一种解决问题的思想能力
◆创建型模式:
◆单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式。
◆结构型模式:
◆适配器模式,桥接模式,装饰模式,组合模式,外观模式,享元模式,代理模式◆行为型模式:
◆模板方法模式,命令模式,迭代器模式,观察者模式,中介者模式,备忘录模式,解释器模式,状态模式,策略模式,职责链模式,访问者模式。
4 0PG七大原则
◆开闭原则:对扩展开放,对修改关闭
◆里氏替换原则:继承必须确保超类所拥有的性质在子类中仍然成立
◆依赖倒置原则:要面向接口编程,不要面向实现编程。
◆单一职责原则:控制类的粒度大小、将对象解耦、 提高其内聚性。
◆接口隔离原则:要为各个类建立它们需要的专用接口
◆迪米特法则:只与你的直接朋友交谈,不跟“陌生人”说话。
◆合成复用原则:尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
5 Java的23设计模式的以下的内容大概介绍:
1 创建型模式
创建型模式 对象实例化的模式,创建型模式用于解耦对象的实例化过程。
单例模式:某个类智能有一个实例,提供一个全局的访问点。
工厂模式:一个工厂类根据传入的参量决定创建出哪一种产品类的实例。
抽象工厂模式:创建相关或依赖对象的家族,而无需明确指定具体类。
建造者模式:封装一个复杂对象的创建过程,并可以按步骤构造。
原型模式:通过复制现有的实例来创建新的实例。
2 结构型模式:把类或对象结合在一起形成一个更大的结构。
装饰器模式:动态的给对象添加新的功能。
代理模式:为其它对象提供一个代理以便控制这个对象的访问。
桥接模式:将抽象部分和它的实现部分分离,使它们都可以独立的变化。
适配器模式:将一个类的方法接口转换成客户希望的另一个接口。
组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构。
外观模式:对外提供一个统一的方法,来访问子系统中的一群接口。
享元模式:通过共享技术来有效的支持大量细粒度的对象。
3 行为型模式:类和对象如何交互,及划分责任和算法。
策略模式:定义一系列算法,把他们封装起来,并且使它们可以相互替换。
模板模式:定义一个算法结构,而将一些步骤延迟到子类实现。
命令模式:将命令请求封装为一个对象,使得可以用不同的请求来进行参数化。
迭代器模式:一种遍历访问聚合对象中各个元素的方法,不暴露该对象的内部结构。
观察者模式:对象间的一对多的依赖关系。
仲裁者模式:用一个中介对象来封装一系列的对象交互。
备忘录模式:在不破坏封装的前提下,保持对象的内部状态。
解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器。
状态模式:允许一个对象在其对象内部状态改变时改变它的行为。
责任链模式:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。
访问者模式:不改变数据结构的前提下,增加作用于一组对象元素的新功能。
第二部分 代理模式:为其它对象提供一个代理以便控制这个对象的访问 进入静态代理模式的学习 这里会用两个案例来讲述什么是 代理模式 这里的每种模式是一种思维 要读者去理解其思维的能力
代理模式的好处:
●可以使真实角色的操作更加纯粹!不用去关注一 些公共的业务●公共也就就交给代理角色!实现了业务的分工!
●公共业务发生扩展的时候,方便集中管理!
缺点:
●一个真实角色就会产生-个代理角色;代码量会翻倍~开发效率会变低~
下面用几张图来理解什么是代理模式哦
案例一
案例二
角色分析
案例一 抽象角色一般是接口或者是实现类 中介
package coms.Design.Mode.Demo1; /** * 代理模式 */ public interface Rent { public void rent(); public void x(); }
package coms.Design.Mode.Demo1; /** * 中介这个角色 */ public class Proxy implements Rent { private Host host; public Proxy() { } public Proxy(Host host) { this.host = host; } @Override public void rent() { host.rent(); } @Override public void x() { host.x(); } //看房子 public void seeHse() { System.out.println("中介带你看房子"); } //收费 public void money() { System.out.println("收中介费"); } //合同 public void Heh() { System.out.println("合同"); } public void Phone(){ System.out.println("中介带电话给房东明确交房的时间"); } }
房东 也要出租房子
package coms.Design.Mode.Demo1; //房东 租房 public class Host implements Rent{ @Override public void rent() { System.out.println("房东要租房子,要出租房子"); } @Override public void x() { System.out.println("我要执行的是X方法"); } }
package coms.Design.Mode.Demo1; /** * 操作的内容单一 */ public class Client { public static void main(String[] args) { Host host=new Host(); // host.rent(); //代理 Proxy proxy = new Proxy(host); proxy.rent(); proxy.seeHse(); proxy.money(); proxy.Heh(); proxy.Phone(); proxy.x(); } }
"C:\Program Files\Java\jdk1.8.0_171\bin\java.exe" "-javaagent:D:\IDEA\com.text\IntelliJ IDEA 2020.1.2\lib\idea_rt.jar=58971:D:\IDEA\com.text\IntelliJ IDEA 2020.1.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_171\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\rt.jar;D:\SSM\com.JavaBasics\out\production\com.JavaBasics" coms.Design.Mode.Demo1.Client 房东要租房子,要出租房子 中介带你看房子 收中介费 合同 中介带电话给房东明确交房的时间 我要执行的是X方法 Process finished with exit code 0
上面是运行结果 思考一下上面的代码是不是可以优化呀!
案例二
package coms.Design.Mode.Demo02; public interface UserService { void adds(); void delete(); void update(); void query(); }
package coms.Design.Mode.Demo02; /** * 正式的对象 */ public class UserServiceImp implements UserService{ @Override public void adds() { System.out.println("增加一条数据"); } @Override public void delete() { System.out.println("删除一条数据"); } @Override public void update() { System.out.println("修改一条数据"); } @Override public void query() { System.out.println("查询一条数据"); } }
package coms.Design.Mode.Demo02; public class UserServiceProxy implements UserService { private UserServiceImp userService; public void setUserService(UserServiceImp userService){ this.userService=userService; } @Override public void adds() { log("增加"); userService.adds(); } @Override public void delete() { log("修改"); userService.delete(); } @Override public void update() { userService.update(); } @Override public void query() { userService.query(); } //日 public void log(String msg){ System.out.println("使用了"+msg+"msg想方法"); } }
Java动态代理 四种方式
案例三:
JDK动态代理:运行期动态的创建代理类,只支持接口。
ASM:一个 Java 字节码操控框架。它能够以二进制形式修改已有类或者动态生成类。不过ASM在创建class字节码的过程中,操纵的级别是底层JVM的汇编指令级别,这要求ASM使用者要对class组织结构和JVM汇编指令有一定的了解;cglib基于ASM实现动态代理。
javassist:一个开源的分析、编辑和创建Java字节码的类库(源码级别的类库)。javassist是jboss的一个子项目,其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类;
bytebuddy:一个更高层次操作字节码的工具包。
Aop代码底层的本质是动态代理
package coms.Design.Mode.Demo03; /** * 代理模式 */ public interface Rent { public void rent(); }
package coms.Design.Mode.Demo03; //房东 租房 public class Host implements Rent { @Override public void rent() { System.out.println("房东要租房子,要出租房子"); } }
package coms.Design.Mode.Demo03; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 等会用这个类自动生成代理类 */ //处理代理实例并返回的结果 public class ProxyInvocationHandler implements InvocationHandler { //被代理的接口 private Rent rent; public void setRent(Rent rent) { this.rent = rent; } //生成代理类 固定代码 public Object getProxy() { // 类的位置 接口 应用对象 return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //动代代理的机制本质又是反射机制 first(); setHandler(); Object result = method.invoke(rent, args); farer(); end(); return result; } public void setHandler(){ System.out.println("中介在看房子"); } public void farer(){ System.out.println("看完后收中介费"); } public void first(){ System.out.println("去中介哪里找房子"); } public void end(){ System.out.println("收合同"); } }
案例三和案例一对比你会发现不同哦! 因为案例三实现了动态代理