程序的耦合
分类:
- (1)内容耦合。当一个模块直接修改或操作另一个模块的数据时,或一个模块不通过正常入口而转入另
- 一个模块时,这样的耦合被称为内容耦合。内容耦合是最高程度的耦合,应该避免使用之。
- (2)公共耦合。两个或两个以上的模块共同引用一个全局数据项,这种耦合被称为公共耦合。在具有大
- 量公共耦合的结构中,确定究竟是哪个模块给全局变量赋了一个特定的值是十分困难的。
- (3) 外部耦合 。一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传
- 递该全局变量的信息,则称之为外部耦合。
- (4) 控制耦合 。一个模块通过接口向另一个模块传递一个控制信号,接受信号的模块根据信号值而进
- 行适当的动作,这种耦合被称为控制耦合。
- (5)标记耦合 。若一个模块 A 通过接口向两个模块 B 和 C 传递一个公共参数,那么称模块 B 和 C 之间
- 存在一个标记耦合。
- (6) 数据耦合。模块之间通过参数来传递数据,那么被称为数据耦合。数据耦合是最低的一种耦合形
- 式,系统中一般都存在这种类型的耦合,因为为了完成一些有意义的功能,往往需要将某些模块的输出数据作为另
- 一些模块的输入数据。
- (7) 非直接耦合 。两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实
内聚
-
标志一个模块内各个元素彼此结合的紧密程度,它是信息隐蔽和局部化概念的自然扩展
-
低耦合,高内聚
-
耦合:程序间的依赖关系
-
包括:
-
类之间的依赖
-
方法间的依赖
-
解耦
-
降低程序间的依赖关系
-
实际开发中:
-
应该做到:编译期不依赖,运行时依赖
解耦思路
- 第一步:使用反射创建对象,而避免使用new
- 第二步:通过读取配置文件来获取要创建对象的名称
-
DriverManager.registerDriver(com.mysql.jdbc.Driver)
-
Class.forname("com.mysql.jdbc.Driver))")
BeanFactory 和 ApplicationContext 的区别
- BeanFactory 才是 Spring 容器中的顶层接口。
- ApplicationContext 是它的子接口。
- BeanFactory 和 ApplicationContext 的区别:
- 创建对象的时间点不一样。
- ApplicationContext:只要一读取配置文件,默认情况下就会创建对象。
- BeanFactory:什么使用什么时候创建对象。
ApplicationContext 接口的实现类
- ClassPathXmlApplicationContext:
- 它是从类的根路径下加载配置文件 推荐使用这种
- FileSystemXmlApplicationContext:
- 它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
- AnnotationConfigApplicationContext:
- 当我们使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。
IOC 中 bean 标签和管理对象细节
bean 标签
作用:
- 用于配置对象让 spring 来创建的。
- 默认情况下它调用的是类中的无参构造函数。如果没有无参构造函数则不能创建成功。
属性:
- id:给对象在容器中提供一个唯一标识。用于获取对象。
- class:指定类的全限定类名。用于反射创建对象。默认情况下调用无参构造函数。
- scope:指定对象的作用范围。
-
- singleton :默认值,单例的.
-
- prototype :多例的.
-
- request :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中.
-
- session :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中.
-
- global session :WEB 项目中,应用在 Portlet 环境.如果没有 Portlet 环境那么
- globalSession 相当于 session.
- init-method:指定类中的初始化方法名称。
- destroy-method:指定类中销毁方法名称。
bean 的作用范围和生命周期
- 单例对象:scope=“singleton”
一个应用只有一个对象的实例。它的作用范围就是整个引用。
生命周期:
对象出生:当应用加载,创建容器时,对象就被创建了。 对象活着:只要容器在,对象一直活着。 对象死亡:当应用卸载,销毁容器时,对象就被销毁了。
- 多例对象:scope=“prototype”
每次访问对象时,都会重新创建对象实例。
生命周期:
对象出生:当使用对象时,创建新的对象实例。 对象活着:只要对象在使用中,就一直活着。 对象死亡:当对象长时间不用时,被 java 的垃圾回收器回收了。
实例化 Bean 的三种方式
第一种方式:使用默认无参构造函数
<!--在默认情况下:
它会根据默认无参构造函数来创建类对象。如果 bean 中没有默认无参构造函数,将会创建失败。
-->
an id="accountService" class="com.itheima.service.impl.AccountServiceImpl"/>
er种方式:spring 管理静态工厂-使用静态工厂的方法创建对象
- id 属性:指定 bean 的 id,用于从容器中获取
- class 属性:指定静态工厂的全限定类名
- factory-method 属性:指定生产对象的静态方法
三种方式:spring 管理实例工厂-使用实例工厂的方法创建对象
- 模拟一个实例工厂,创建业务层实现类
- 此工厂创建对象,必须现有工厂实例对象,再调用方法
此种方式是:
先把工厂的创建交给 spring 来管理。
然后在使用工厂的 bean 来调用里面的方法
- factory-bean 属性:用于指定实例工厂 bean 的 id。
- factory-method 属性:用于指定实例工厂中创建对象的方法。
Spring的优点
- 降低了组件之间的耦合性,实现了软件各层之间的解耦
- 可以使用容易提供的众多服务,如事务管理,消息服务
- 容器提供单例模式支持
- 容器提供AOP技术,利用它很容易i实现如权限拦截,运行期监控等功能
- 容器提供了众多辅助类,能加快应用的开发
- spring对于主流的应用框架提供了继承支持,如hibernate,JPA,Struts等
- spring属于低侵式设计,代码的污染极低
- 独立于各种服务器
- spring的Id机制降低了业务对象替换的复杂度
- Spring的高度开放性,并不强制应用完全依赖于spring,开发者可以自由的选择spring的部分或全部
DI机制
依赖注入和控制反转是同一个概念,当某个角色需要另外一个角色协助的时候,在传统程序设计中,通常由调用者来创建被调用者的实例.但创建被调用者的工作由spring来完成,然后注入调用者,因此也被称为依赖注入.
注入方式
- 设置注入:直观,自然
- 构造注入:可以在构造器中决定依赖关系的顺序
构造函数注入
要求:
类中需要提供一个对应参数列表的构造函数。
涉及的标签:
constructor-arg
属性:
- index:指定参数在构造函数参数列表的索引位置
- type:指定参数在构造函数中的数据类型
- name:指定参数在构造函数中的名称 用这个找给谁赋值
上面三个都是找给谁赋值,下面两个指的是赋什么值的
- value:它能赋的值是基本数据类型和 String 类型
- ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean
set 方法注入
通过配置文件给 bean 中的属性传值:使用 set 方法的方式
涉及的标签:
property
属性:
- name:找的是类中 set 方法后面的部分
- ref:给属性赋值是其他 bean 类型的
- value:给属性赋值是基本数据类型和 string 类型的
- 实际开发中,此种方式用的较多。
使用 p 名称空间注入数据(本质还是调用 set 方法)
注入集合属性
注入集合数据
- List 结构的:
- array,list,set
- Map 结构的
- map,entry,props,prop
- 在注入集合数据时,只要结构相同,标签可以互换
基于注解的 IOC 配置
用于创建对象的
@Component
作用:
把资源让 spring 来管理。相当于在 xml 中配置一个 bean。
属性:
value:指定 bean 的 id。如果不指定 value 属性,默认 bean 的 id 是当前类的类名。首字母小写。
@Controller @Service @Repository
- 他们三个注解都是针对一个的衍生注解,他们的作用及属性都是一模一样的。
- 他们只不过是提供了更加明确的语义化。
- @Controller:一般用于表现层的注解。
- @Service:一般用于业务层的注解。
- @Repository:一般用于持久层的注解。
细节:如果注解中有且只有一个属性要赋值时,且名称是 value,value 在赋值是可以不写。
用于注入数据的
@Autowired
自动按照类型注入
@Qualifier
作用:
在自动按照类型注入的基础之上,再按照 Bean 的 id 注入。它在给字段注入时不能独立使用,必须和 @Autowire 一起使用;但是给方法参数注入时,可以独立使用。
属性:
value:指定 bean 的 id。
@Resource
作用:
直接按照 Bean 的 id 注入。它也只能注入其他 bean 类型。
属性:
name:指定 bean 的 id。
@Value
作用:
注入基本数据类型和 String 类型数据的
属性:
value:用于指定值
用于改变作用范围的:
@Scope
和生命周期相关的:(了解)
- @PostConstruct
- @PreDestroy
新注解说明
- @Configuration
指定当前类是一个 spring 配置类
- @ComponentScan
指定 spring 在初始化容器时要扫描的包
-@Bean
作用:该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器。
属性:name:给当前@Bean 注解方法创建的对象指定一个名称(即 bean 的 id)。
- @PropertySource
用于加载.properties 文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到
properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。
属性:
value[]:用于指定 properties 文件位置。如果是在类路径下,需要写上 classpath:
Spring 整合 Junit
- 拷贝整合 junit 的必备 jar 包到 lib 目录
- 使用@RunWith 注解替换原有运行器
- 使用@ContextConfiguration 指定 spring 配置文件的位置
- 使用@Autowired 给测试类中的变量注入数据
AOP
面向切面编程(AO’p)完善spring的依赖注入(DI),面向切面编程在spring中主要编年在两个方面
- 面向切面编程提供生命式事务管理
- spring支持用户自定义的切面
Joinpoint(连接点):
所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的连接点。
- Pointcut(切入点):
- 所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义。
- Advice(通知/增强):
所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。
通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。
- Introduction(引介):
引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类动态地添加一些方法或 Field。
- Target(目标对象):
代理的目标对象。
- Weaving(织入):
是指把增强应用到目标对象来创建新的代理对象的过程。
spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入
- Proxy(代理):
一个类被 AOP 织入增强后,就产生一个结果代理类。
- Aspect(切面):
是切入点和通知(引介)的结合。
- 第一步:把通知类用 bean 标签配置起来
- 第二步:使用 aop:config 声明 aop 配置
- 第三步:使用 aop:aspect 配置切面
- 第四步:使用 aop:pointcut 配置切入点表达式
- 第五步:使用 aop:xxx 配置对应的通知类型
切入点表达式说明
execution([修饰符] 返回值类型 包名.类名.方法名(参数))
- 面向切面编程(aop)
- 是对面向对象编程(oop)的补充 面向对象编程将程序分解成各个层次的对象,面向切面编程将程序运行过程分解成各个切面。
- AOP从程序运行角度考虑程序的结构,提取业务处理过程的切面,oop是静态的抽象,aop是动态的抽象,
- 是对应用执行过程中的步骤进行抽象,,从而获得步骤之间的逻辑划分。
AOP框架具有的两个特征
1.各个步骤之间的良好隔离性
2.源代码无关性
SpringBoot 特性
- 创建独立的spring应用程序
- 潜入的Tomacat,无需部署WAR文件
- 简化maven配置
- 自动配置Spring
- 提供生产就绪功能,如指标,健康检查和外部配置
- 开箱即用,没有代码生成,也`无需xml配置
spring容器
- Spring BeanFactory
BeanFactoryAware,InitializingBean,DisposableBean - Spring ApplicationContext
从一个属性文件中解析文本信息的能力,发布应用程序事件给感兴趣的事件监听器的能力 - ApplicationContext 容器包括 BeanFactory 容器的所有功能,所以通常建议超过 BeanFactory。
- BeanFactory 仍然可以用于轻量级的应用程序,如移动设备或基于 applet 的应用程序,其中它的数据量和速度是显著。
-在资源宝贵的移动设备或者基于 applet 的应用当中, BeanFactory 会被优先选择。否则,一般使用的是 ApplicationContext,除非你有更好的理由选择 BeanFactory
最常被使用的 ApplicationContext 接口实现
-
FileSystemXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你需要提供给构造器 XML 文件的完整路径。
-
ClassPathXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你不需要提供 XML 文件的完整路径,只需正确配置 CLASSPATH 环境变量即可,因为,容器会从 CLASSPATH 中搜索 bean 配置文件。
-
WebXmlApplicationContext:该容器会在一个 web 应用程序的范围内加载在 XML 文件中已被定义的 bean。
单例对象和多例对象
单例对象:从始至终只有一个对象
只被创建一次,类成员只会被初始化一次,
多例对象:每次都是新的对象
每个对象都被重新初始化,执行效率低