软件开发原则
-
OCP
- 什么是OCP?
- OCP是软件七大开发原则中最基本的一个原则:开闭原则。
即对扩展开放,对修改关闭。
- OCP是软件七大开发原则中最基本的一个原则:开闭原则。
- OCP原则是最核心的,最基本的,其他六个原则都是为了这个原则服务的。
- OCP开闭原则的核心是什么?
- 只要在拓展系统功能的时候,没有修改以前写好的代码,那么就是符合OCP原则的;
反之,如果在扩展功能的同时修改了之前的代码,那么这个设计就是失败的,是违背OCP原则的。
- 只要在拓展系统功能的时候,没有修改以前写好的代码,那么就是符合OCP原则的;
- 当进行系统功能扩展的时候,如果改动了之前稳定的程序,那么整个业务流程都需要重新测试,这不是我们希望看到的结果。
- 什么是OCP?
-
依赖倒置原则(DIP原则)
- 面向接口编程,面向抽象编程,不要面向过程。
- 目的是降低程序的耦合度,提高扩展能力。
-
控制反转原则(IoC)
- 第一,不要在程序中采用硬编码的方式去new对象。(new对象我不管了,new对象的权力我也交出去了)
- 第二,不要在程序中采用硬编码的方式去维护对象关系了。(对象之间关系的维护我也不管了,也交出去。)
-
spring框架
- Spring框架实现了控制反转IoC这种思想
- spring框架可以帮你new对象,并维护对象与对象之间的关系。
- Spring是一个实现了IoC思想的容器。
- 控制反转的实现方式有很多种,其中比较重要的是:依赖注入(DI)。
- 依赖注入DI,又包含了两种常见方式:
- 第一种:set注入(执行set方法给属性赋值)
- 第二种:构造方法注入(执行构造方法给属性赋值)
- 依赖注入中,依赖是指A对象与B对象的关系,注入是指通过某种手段使A对象和B对象产生关系。
- Spring框架实现了控制反转IoC这种思想
-
术语总结
- OCP:开闭原则(开发原则)
- DIP:依赖倒置原则(开发原则)
- IoC:控制反转(一种思想,一种新型的设计模式)
- DI:依赖注入(控制反转的具体实现方式)
Spring特点
- 轻量
- 从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。
- Spring是非侵入式的:Spring应用中的对象不依赖于Spring的特定类。
- 控制反转
- Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。
- 面向切面
- Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
- 容器
- Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。
- 框架
- Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。
所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。
Spring对IoC的实现
- IoC 控制反转
- 控制反转是一种思想。
- 控制反转是为了降低程序耦合度,提高程序扩展力,达到OCP原则,达到DIP原则。
- 控制反转,反转的是什么?
- 将对象的创建权利交出去,交给第三方容器负责。
- 将对象和对象之间关系的维护权交出去,交给第三方容器负责。
- 控制反转这种思想如何实现呢?
- DI(Dependency Injection):依赖注入
- 依赖注入
- 依赖注入实现了控制反转的思想。
- Spring通过依赖注入的方式来完成Bean管理的。
- Bean管理说的是:Bean对象的创建,以及Bean对象中属性的赋值(或者叫做Bean对象之间关系的维护)。
- 依赖注入:
- 依赖指的是对象和对象之间的关联关系。
- 注入指的是一种数据传递行为,通过注入行为来让对象和对象产生关系。
- 依赖注入常见的实现方式包括两种:
- 第一种:set注入
- 第二种:构造注入
- 控制反转实现了
Bean的实例化方式
- Spring为Bean提供了多种实例化方式,通常包括4种方式。(也就是说在Spring中为Bean对象的创建准备了多种方案,目的是:更加灵活)
- 第一种:通过构造方法实例化
- 第二种:通过简单工厂模式实例化
- 第三种:通过factory-bean实例化
- 第四种:通过FactoryBean接口实例化
BeanFactory和FactoryBean
- BeanFactory
- Spring IoC容器的顶级对象,BeanFactory被翻译为“Bean工厂”,在Spring的IoC容器中,“Bean工厂”负责创建Bean对象。
BeanFactory是工厂。
- Spring IoC容器的顶级对象,BeanFactory被翻译为“Bean工厂”,在Spring的IoC容器中,“Bean工厂”负责创建Bean对象。
- FactoryBean
- FactoryBean:它是一个Bean,是一个能够辅助Spring实例化其它Bean对象的一个Bean。
在Spring中,Bean可以分为两类:- 第一类:普通Bean
- 第二类:工厂Bean(记住:工厂Bean也是一种Bean,只不过这种Bean比较特殊,它可以辅助Spring实例化其它Bean对象。)
- FactoryBean:它是一个Bean,是一个能够辅助Spring实例化其它Bean对象的一个Bean。
Bean的生存周期
- 七步生命周期:
- 十步生命周期
Aware相关的接口包括:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware:- 当Bean实现了BeanNameAware,Spring会将Bean的名字传递给Bean。
- 当Bean实现了BeanClassLoaderAware,Spring会将加载该Bean的类加载器传递给Bean。
- 当Bean实现了BeanFactoryAware,Spring会将Bean工厂对象传递给Bean。
- 注意:spring只对单例Bean提供生命周期管理,对于多例Bean,Spring只负责到初始化结束,当客户端获取到该Bean时,Spring就不再管理该Bea的n生命周期了。
循环依赖
- Spring可以在set + singleton模式下解决循环依赖(一个单例一个多例也可以)。
- 根本的原因在于:这种方式可以做到将“实例化Bean”和“给Bean属性赋值”这两个动作分开去完成。
- 实例化Bean的时候:调用无参数构造方法来完成。此时可以先不给属性赋值,可以提前将该Bean对象“曝光”给外界。
也就是说,Bean都是单例的,我们可以先把所有的单例Bean实例化出来,放到一个集合当中(我们可以称之为缓存),所有的单例Bean全部实例化完成之后,以后我们再慢慢的调用setter方法给属性赋值。这样就解决了循环依赖的问题。
反射机制
实例:
package com.powernode.reflect;
import java.lang.reflect.Method;
public class UserTest {
public static void main(String[] args) throws Exception{
// 已知类名
String className = "reflect.User";
// 已知属性名
String propertyName = "age";
// 通过反射机制给User对象的age属性赋值20岁
Class<?> clazz = Class.forName(className);
Object obj = clazz.newInstance(); // 创建对象
// 根据属性名获取setter方法名
String setMethodName = "set" + propertyName.toUpperCase().charAt(0) + propertyName.substring(1);
// 获取Method
Method setMethod = clazz.getDeclaredMethod(setMethodName, int.class);
// 调用Method
setMethod.invoke(obj, 20);
System.out.println(obj);
}
}
Spring IoC注解式开发
- 注解的存在主要是为了简化XML的配置。Spring6倡导全注解开发。
- 没仔细研究,后续再补充内容。
AOP介绍
- 一般一个系统当中都会有一些系统服务,例如:日志、事务管理、安全等。这些系统服务被称为:交叉业务
这些交叉业务几乎是通用的,不管你是做银行账户转账,还是删除用户数据。日志、事务管理、安全,这些都是需要做的。
如果在每一个业务处理过程当中,都掺杂这些交叉业务代码进去的话,存在两方面问题:- 第一:交叉业务代码在多个业务流程中反复出现,显然这个交叉业务代码没有得到复用。并且修改这些交叉业务代码的话,需要修改多处。
- 第二:程序员无法专注核心业务代码的编写,在编写核心业务代码的同时还需要处理这些交叉业务。
- 放一张图快速理解AOP的思想:
- AOP的底层逻辑是通过代理模式(动态代理)实现的,使用了JDK动态代理 + CGLIB动态代理技术。
- Spring在这两种动态代理中灵活切换,如果是代理接口,会默认使用JDK动态代理,如果要代理某个类,这个类没有实现接口,就会切换使用CGLIB。当然,你也可以强制通过一些配置让Spring只使用CGLIB。
- 用一句话总结AOP:
将与核心业务无关的代码独立的抽取出来,形成一个独立的组件,然后以横向交叉的方式应用到业务流程当中的过程被称为AOP。
AOP的优点:- 第一:代码复用性增强。
- 第二:代码易维护。
- 第三:使开发者更关注业务逻辑。
- AOP术语
- 连接点 Joinpoint
在程序的整个执行流程中,可以织入切面的位置。方法的执行前后,异常抛出之后等位置。 - 切点 Pointcut
在程序执行流程中,真正织入切面的方法。(一个切点对应多个连接点) - 通知 Advice
通知又叫增强,就是具体你要织入的代码。- 通知包括:
- 前置通知
- 后置通知
- 环绕通知
- 异常通知
- 最终通知
- 切面 Aspect
切点 + 通知就是切面。 - 织入 Weaving
把通知应用到目标对象上的过程。 - 代理对象 Proxy
一个目标对象被织入通知后产生的新对象。 - 目标对象 Target
被织入通知的对象。
- 连接点 Joinpoint
- SpringAOP
Spring对AOP的实现包括以下3种方式:
第一种方式:Spring框架结合AspectJ框架实现的AOP,基于注解方式。
第二种方式:Spring框架结合AspectJ框架实现的AOP,基于XML方式。
第三种方式:Spring框架自己实现的AOP,基于XML配置方式。 - execution([访问控制权限修饰符] 返回值类型 [全限定类名]方法名(形式参数列表) [异常])
- 访问控制权限修饰符:
- 可选项。
- 没写,就是4个权限都包括。
- 写public就表示只包括公开的方法。
- 返回值类型:
- 必填项。
- * 表示返回值类型任意。
- 全限定类名:
- 可选项。
- 两个点“…”代表当前包以及子包下的所有类。
- 省略时表示所有的类。
- 方法名:
- 必填项。
- * 表示所有方法
- set*表示所有的set方法。
- 形式参数列表:
- 必填项
- () 表示没有参数的方法
- (…) 参数类型和个数随意的方法
- ( * ) 只有一个参数的方法
- ( * , String) 第一个参数类型随意,第二个参数是String的。
- 异常:
- 可选项。
- 省略时表示任意异常类型。
- 访问控制权限修饰符: