spring的控制反转
什么是程序间的耦合
耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调
用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关
系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立
性)。耦合性存在于各个领域,而非软件设计中独有的,但是我们只讨论软件工程中的耦合。
在软件工程中,耦合指的就是就是对象之间的依赖性。对象之间的耦合越高,维护成本越高。因此对象的设计
应使类和构件之间的耦合最小。软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。划分模块的一个
准则就是高内聚低耦合。
它有如下分类:
(1)内容耦合。当一个模块直接修改或操作另一个模块的数据时,或一个模块不通过正常入口而转入另
一个模块时,这样的耦合被称为内容耦合。内容耦合是最高程度的耦合,应该避免使用之。
(2)公共耦合。两个或两个以上的模块共同引用一个全局数据项,这种耦合被称为公共耦合。在具有大
量公共耦合的结构中,确定究竟是哪个模块给全局变量赋了一个特定的值是十分困难的。
(3) 外部耦合 。一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传
递该全局变量的信息,则称之为外部耦合。
(4) 控制耦合 。一个模块通过接口向另一个模块传递一个控制信号,接受信号的模块根据信号值而进
行适当的动作,这种耦合被称为控制耦合。
(5)标记耦合 。若一个模块 A 通过接口向两个模块 B 和 C 传递一个公共参数,那么称模块 B 和 C 之间
存在一个标记耦合。
(6) 数据耦合。模块之间通过参数来传递数据,那么被称为数据耦合。数据耦合是最低的一种耦合形
式,系统中一般都存在这种类型的耦合,因为为了完成一些有意义的功能,往往需要将某些模块的输出数据作为另
一些模块的输入数据。
(7) 非直接耦合 。两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实
现的。
总结:
耦合是影响软件复杂程度和设计质量的一个重要因素,在设计上我们应采用以下原则:如果模块间必须
存在耦合,就尽量使用数据耦合,少用控制耦合,限制公共耦合的范围,尽量避免使用内容耦合。
内聚与耦合
内聚标志一个模块内各个元素彼此结合的紧密程度,它是信息隐蔽和局部化概念的自然扩展。内聚是从
功能角度来度量模块内的联系,一个好的内聚模块应当恰好做一件事。它描述的是模块内的功能联系。耦合是软件
结构中各模块之间相互连接的一种度量,耦合强弱取决于模块间接口的复杂程度、进入或访问一个模块的点以及通
过接口的数据。 程序讲究的是低耦合,高内聚。就是同一个模块内的各个元素之间要高度紧密,但是各个模块之
间的相互依存度却要不那么紧密。
内聚和耦合是密切相关的,同其他模块存在高耦合的模块意味着低内聚,而高内聚的模块意味着该模块同其他
模块之间是低耦合。在进行软件设计时,应力争做到高内聚,低耦合。
工厂模式解耦合
在实际开发的过程中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用的加载的时候,让一个类的中的方法去解析配置文件,把这些对象创建出来并存起来,在接下来的使用的时候,直接拿过来使用就好了,那么读取配置文件,创建和获取三层对象的类就是工厂
控制反转
控制反转:inversion of Control 英文缩写IOC,把创建对象的权利交给框架是框架的重要的特征,并非面向对象编程的专用术语,它包含依赖注入和依赖查找,明确我们IOC的作用是消减程序间的依赖,并非是全部消除
1.1bean中的标签
1.1作用
用于配置对象让Spring来创建
默认是调用类中的无参的构造方法,如果没有无参的构造方法,如果没有无参的构造方法,则不能创建成功
1.2属性
id:给对象在容器中的唯一标识,用于获取对象
class:值得是类的全限定类名,用于反射对象,默认是调用无参的构造方法
scope:指定的是对象的作用范围,默认是单例的模式:singleton,默认的单例的模式,prototype,多例的
init-method:指类中的初始化方法名称
destroy-method :指类中的销毁方法
1.3写接口以及实现类
package cn.ujiuye.service;
/**
* @author liugang
* @date 2019/10/4
* 账户的业务层接口
*/
public interface IAccountService {
/**
* 模拟保存账号
*/
void saveAccount();
}
package cn.ujiuye.service;
/**
* @author liugang
* @date 2019/10/4
* 账户的业务层接口
*/
public interface IAccountService {
/**
* 模拟保存账号
*/
void saveAccount();
}
package cn.ujiuye.service.impl;
import cn.ujiuye.service.IAccountService;
/**
* @author liugang
* @date 2019/10/4
* 账号的业务层实现类
*/
public class AccountServiceImpl implements IAccountService {
public AccountServiceImpl(){
System.out.println("对象创建了");
}
public void saveAccount() {
System.out.println("service中的saveAccount的方法执行了");
}
/**
* 初始化方法
*/
public void init() {
System.out.println("对象初始化了");
}
/**
* 销毁方法
*/
public void destory() {
System.out.println("对象销毁了");
}
}
package cn.ujiuye.service.impl;
import cn.ujiuye.dao.IAccountDao;
import cn.ujiuye.dao.impl.AccountDaoImpl;
import cn.ujiuye.service.IAccountService;
/**
* @author liugang
* @date 2019/10/4
* 账号的业务层实现类
*/
public class AccountServiceImpl implements IAccountService {
private IAccountDao accountDao;
public AccountServiceImpl(){
System.out.println("对象创建了");
}
public void saveAccount() {
//当不赋值的时候,根据错误类型
accountDao.saveAccount();
}
}
1.4.在bean.xml中配置相对于的数据的配置,让对象的创建交给spring来管理
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--把对象的创建交给spring来管理-->
<bean id="accountService" class="cn.ujiuye.service.impl.AccountServiceImpl"></bean>
<bean id="accountDao" class="cn.ujiuye.dao.impl.AccountDaoImpl"></bean>
</beans>
package cn.ujiuye.ui;
import cn.ujiuye.dao.IAccountDao;
import cn.ujiuye.service.IAccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author liugang
* @date 2019/10/4
* 模拟了一个表现层,用于调用业务逻辑层
*/
public class Client {
/**
* 获取spring的Ioc的核心容器,并根据id获取对象
* applicationContext的常用的三个实现类
* ClassPathXmlApplicationContext 它可以加载类路径下的配置文件,要求配置文件必须在类的路径下,不在的话,加载不了(常用)
* FileSystemXmlApplicationContext 它可以加载磁盘的任意的路径下的配置文件(必须有访问权限)
* AnnotationConfigApplicationContext 它是读取注解创建容器的
*
* 核心容器的两个接口引发的问题
* ApplicationContext 单例对象实用 采用此接口
* 它在构建核心容器时.创建对象采用的立即加载的方式,也就是说一读取到配置文件就立即创建配置文件中的对象
* BeanFactory 多例对象实用
* 它在创建核心容器时,创建对象采用的策略是延迟加载的方式,也就是说什么时候根据id创建对象了,什么时候才创建真正的对象
*
*
* @param args
*/
public static void main(String[] args) {
//IAccountService as = new AccountServiceImpl();
//1.获取核心容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//2.根据id获取Bean对象
IAccountService as = (IAccountService) ac.getBean("accountService");
IAccountDao adao = ac.getBean("accountDao", IAccountDao.class);
System.out.println(as);
System.out.println(adao);
//调用service方法来实现其效果
as.saveAccount();
}
}