一、Spring概述

(1)Spring的概念
Spring是分层的 Java SE/EE应用 full-stack(全栈式) 轻量级开源框架。

在这里插入图片描述
IoC(Inverse Of Control:反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核提供了展现层 SpringMVC持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术。在这里插入图片描述

还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的Java EE 企业应用开源框架。例如SSM:Spring、SpringMVC、Mybatis的一个整合

(2)Spring的优势
1.方便解耦,简化开发:
通过提供的IoC容器,可以将对象间的依赖关系交由 Spring进行控制,避免硬编码所造成的过度程序耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。随之而来的是底层原理的复杂。

2.AOP 编程的支持

3。声明式事务的支持
可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务的管理,
提高开发效率和质量。

4.方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可
做的事情。

5.方便集成各种优秀框架
Spring可以降低各种框架的使用难度,提供了对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的直接支持。

6.降低 JavaEE API 的使用难度
Spring对 JavaEE API(如 JDBC、JavaMail、远程调用等)进行了薄薄的封装层,使这些 API 的
使用难度大为降低。

7.Java 源码是经典学习范例
Spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java 设计模式灵活运用以
及对 Java技术的高深造诣。它的源代码无意是 Java 技术的最佳实践的范例。

(3)Spring的体系结构
在这里插入图片描述

二、程序的耦合和解耦

程序的耦合:程序之间的依赖关系。包括:类之间的依赖、方法间的依赖

解耦:降低程序间的依赖关系。所以实际开发中:应该做到的是、编译期不依赖、运行时才依赖。
我们在开发中,有些依赖关系是必须的,有些依赖关系可以通过优化代码来解除的。

(1)对于类的解耦:

(1)使用反射来创建而不是需要依赖导包来new
(2)通过配置文件()来获取参数,避免写死
Class.forName("com.mysql.jdbc.Driver");//此处只是一个字符串

此时的好处是,我们的类中不再依赖具体的驱动类,此时就算删除 mysql 的驱动 jar 包,依然可以编译(运行就不要想了,没有驱动不可能运行成功的)。

同时,也产生了一个新的问题,mysql 驱动的全限定类名字符串是在 java 类中写死的,一旦要改还是要修改源码。

解决这个问题也很简单,使用配置文件配置。Properties props.getProperty();

(2)工厂模式解耦

在实际开发中我们可以把三层的对象都使用配置文件配置起来,让一个类中的方法通过读取配置文件,把这些对象创建出来 并存起来。在接下来的使用的时候,直接拿过来用就好了。

那么,这个读取配置文件,创建和获取三层对象的类就是工厂。

1、Bean

这些对象称之为Bean对象。

Bean:可重用的组件
JavaBean:用java语言编写的可重用组件。(impl,dao,User等实体类都可以说是Bean
JavaBean > 实体类

2、Factory、beans存储

它就是创建我们service和dao对象的。

第一个:需要一个配置文件配置我们的service和dao
配置文件里面放:唯一标识 = 全限定类名 (key = value),定义一个Map,来存放我们创建的对象,称之为容器
第二个:通过配置文件内容来 反射 创建对象
配置文件可以是:XML也可以是properties

/**
* @author Mango
* 一个创建Bean对象的工厂
*/
public class BeanFactory {
/**
* 1.定义一个静态的 配置文件对象
*/
private static Properties props;

/**
* 定义一个Map,来存放我们创建的对象,称之为容器
*/
private static Map<String,Object> beans;

//静态代码块为Properties赋值
static {
try {
props = new Properties();
//获取properties文件的流对象
InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean/properties");
props.load(in);
//实例化容器
beans = new HashMap<String, Object>();
//取出配置文件中所有的key
Enumeration keys =props.keys();
//遍历枚举
while(keys.hasMoreElements()) {
//取出每个key
String key = keys.nextElement().toString();
//根据key来获取value
String beanPath = props.getProperty(key);
//反射来创建对象
Object value = Class.forName(beanPath).newInstance();
//将key和value再返回到容器中
beans.put(key,value);
}
} catch (IOException e) {
throw new ExceptionInInitializerError("初始化properties失败");
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}

最后的配置文件信息都在beans中,三层Service和Web层调用时,使用工厂的getBean(beanName)来获取对象,然后再调用方法。减少耦和度在这里插入图片描述

/**
* @author Mango
* 账户的业务层接口的实现类
*/
public class AccountServiceImpl implements IAccountService {

//private IAccountDao accountDao = new AccountDaoImpl();

private IAccountDao accountDao = (IAccountDao) BeanFactory.getBean("accountDao");

public void saveAccount() {
accountDao.saveAccount();
}
}
/**
* @author Mango
* 模拟一个表现层,用于调用业务层的方法
*/
public class Client {

public static void main(String[] args) {
//IAccountService service = new AccountServiceImpl();
IAccountService service = (IAccountService) BeanFactory.getBean("accountService");
service.saveAccount();
}
}