2022-03-22
三层架构
终于来到Spring框架了,前面讲了Spring MVC和MyBatis框架,现在就讲了Spring框架的作用是什么以及如何在开发中去配置。
Spring框架是Java应用最广的框架,是一个轻量级的开源框架,它的主要理念包括 IoC (Inversion of Control,控制反转) 和 AOP(Aspect Oriented Programming,面向切面编程)。Spring框架的结构,见下图。
Spring框架能实现的功能:
①Spring 能帮我们根据配置文件创建及组装对象之间的依赖关系。
②Spring 面向切面编程能帮助我们无耦合的实现日志记录,性能统计,安全控制。
③Spring 能非常简单的帮我们管理数据库事务。
④Spring 还提供了与第三方数据访问框架(如Hibernate、JPA)无缝集成,而且自己也提供了一套JDBC访问模板来方便数据库访问。
⑤Spring 还提供与第三方Web(如Struts1/2、JSF)框架无缝集成,而且自己也提供了一套Spring MVC框架,来方便web层搭建。
⑥Spring 能方便的与Java EE(如Java Mail、任务调度)整合,与更多技术整合(比如缓存框架)。
Spring框架的意义:
低侵入,方便解耦,简化开发
通过 Spring 提供的 IoC 容器,可以将对象间的依赖关系交由 Spring 进行控制,避免硬编码所造成的过度程序耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
AOP 编程的支持
通过 Spring 的 AOP 功能,方便进行面向切面的编程,许多不容易用传统 OOP 实现的功能可以
通过 AOP 轻松应付。
声明式事务的支持(基于切面和惯例)
可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务的管理,
提高开发效率和质量。
方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可
做的事情。
方便集成各种优秀框架
Spring 可以降低各种框架的使用难度,提供了对各种优秀框架( Struts、 Hibernate、 Hessian、Quartz
等)的直接支持。
降低 JavaEE API 的使用难度
Spring对JavaEE API(如 JDBC、 JavaMail、远程调用等)进行了薄薄的封装层,使这些 API 的
使用难度大为降低。
IoC并不是什么技术,而是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。
正控:若要使用某个对象,需要自己去负责对象的创建,即采用new的方式。
反控:若要使用某个对象,只需要从 Spring 容器中获取需要使用的对象,不关心对象的创建过程,也就是把创建对象的控制权反转给了Spring框架。
IoC的作用:削减计算机程序中的耦合(即解除我们代码中的依赖关系)。
耦合:程序间的依赖关系,包括类之间的依赖和方法之间的依赖。 解耦:降低程序间的依赖关系。 在实际开发中,应该做到:编译期间不依赖,运行时才依赖。 解耦的思路: 1、使用反射来创建对象,而避免使用new关键字来创建对象; 2、通过读取配置文件来获取要创建的对象的全限定类名。接下来,我将通过自定义一个BeanFactory类(先不使用Spring框架),使用工厂模式的方式去解耦程序,从而讲解IoC的大概原理。但首先,我会先通过传统的方式(使用工厂模式前)写一个demo,然后再通过工厂模式去优化代码。
先新建一个项目,目录结构如下:
在该项目中,我将模拟表现层,通过ui中的类Client来调用业务层service中的接口来模拟保存账户(这里只是模拟保存账户,在console中打印“保存了账户”该信息,并不是真的创建并保存一个账户)。
表现层中的com.nick.ui.Client.java,代码如下:
package com.nick.ui; import com.service.IAccountService; import com.nick.service.impl.AccountServiceImpl; /** * 模拟一个表现层,用于调用业务层 * */ public class Client { public static void main(String[] args) { IAccountService as = new AccountServiceImpl(); System.out.println(as); as.saveAccount(); } }
业务层中的com.service.IAccountService.java,代码如下:
业务层中的实现类com.nick.service.impl.AccountServiceImpl,代码如下:
在业务层中通过调用持久层接口的方法来模拟保存账户。
持久层中的com.nick.dao.IAccountDao.java,代码如下:
package com.nick.dao; public interface IAccountDao { void saveAccount(); }
持久层中的实现类com.nick.dao.impl.AccountDaoImpl.java,代码如下:
然后在Client类右键点击运行:
运行成功,这里成功“保存了账户”,并打印了业务层对象。
但是,在上面的代码中,业务层调用持久层,并且此时业务层在依赖持久层的接口和实现类。如果此时没有持久层实现类,编译将不能通过。 在表现中也依赖了业务层的接口和实现类,见下图(通过new的方式来产生依赖),这种编译期依赖关系,应该在我们开发中杜绝,因此我们需要优化代码来解决。
下面,我将对上述代码进行优化,通过工厂模式来减少程序间的耦合。
优化后的项目目录结构如下:
首先创建一个BeanFactory类,一个创建bean的工厂,用于创建service和dao对象。
方法:
1、需要一个配置文件来配置service和dao
配置内容为:key=value -> 唯一标志名=全限定类名
2、通过读取配置文件中的配置内容,反射创建对象
com.nick.factory.BeanFactory.java,代码如下:
package com.nick.factory; import java.io.InputStream; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Properties; /** *一个创建bean的工厂 * 用于创建service和dao对象 *方法: * 1、需要一个配置文件来配置service和dao * 配置内容为:key=value :唯一标志=全限定类名 * 2、通过读取配置文件中的配置内容,反射创建对象 */ public class BeanFactory { //定义一个Properties对象 private static Properties props; //定义一个Map,用于存放我们的对象,该Map对象称之为“容器” private static Map beans; //使用静态代码块为Properties对象赋值 static { try { //实例化对象 props = new Properties(); //获取Properties文件的流对象 InputStream in = BeanFactory.class.getClassLoader() .getResourceAsStream("bean.properties"); props.load(in); //产生单例对象的方式 //实例化容器 beans = new HashMap(); //取出配置文件中的所有的key Enumeration keys = props.keys(); //遍历枚举中的值 while(keys.hasMoreElements()){ //取出每个key String key = keys.nextElement().toString(); //根据key获取bean的路径 String beanPath = props.getProperty(key); //反射创建对象 Object value = Class.forName(beanPath).newInstance(); //把key和value存入容器中 beans.put(key,value); } }catch (Exception e){ throw new ExceptionInInitializerError("初始化Properties对象失败"); } } /** *根据bean的名称获取bean对象 * @param beanName * @return */ //此时获取的对象是单例的 public static Object getBean(String beanName){ //直接通过传入bean的名字来获取容器中的bean对象 return beans.get(beanName); } }在resources目录下新建一个bean的配置文件bean.properties:
accountService=com.nick.service.impl.AccountServiceImpl accountDao=com.nick.dao.impl.AccountDaoImpl
接下来,把原来代码中使用new方式引入依赖的两行代码注释掉,改成使用工厂模式的方法,直接去获取容器中所需的对象。
com.nick.service.impl.AccountServiceImpl,代码如下:
package com.nick.service.impl; import com.nick.dao.IAccountDao; import com.nick.factory.BeanFactory; import com.nick.service.IAccountService; public class AccountServiceImpl implements IAccountService { //private IAccountDao accountDao = new AccountDaoImpl(); IAccountDao accountDao = (IAccountDao) BeanFactory.getBean("accountDao"); public void saveAccount(){ accountDao.saveAccount(); } }
com.nick.ui.Client.java,代码如下:
奇妙商场嘉年华最新版本(改名奇妙故事创造家)下载v9.82.63.00 安卓版
其它手游 192.9M
下载天天爱消除官方下载v2.34.0.0Build13 安卓手机版
休闲益智 341.9M
下载爱玩信阳黑七游戏下载v10.50.208 安卓最新版
其它手游 96.1M
下载掌上英雄联盟ios版下载v10.12.2 iphone版
其它手游 346M
下载咪咕快游云游戏ios版下载v10.2.59 iphone版
其它手游 397M
下载罗布乐思roblox国际服最新版ios下载v2.651.836 iphone版
其它手游 258M
下载傲世西游ios版下载v2.116 iPhone版
其它手游 282M
下载宝宝甜品店宝宝巴士免费版下载v9.82.59.01 安卓版
其它手游 140.9M
下载最强NBA官方版下载v1.51.621 安卓版
下载
蛋仔派对4399版下载v1.0.168 安卓游戏盒版
下载
跑跑卡丁车官方竞速版手游下载v1.34.2 安卓版
下载
宝宝巴士世界国际版下载v10.00.75.21 官方安卓最新版
下载
王者荣耀体验服下载v10.11.13.1 安卓2024最新版
下载
2024王者荣耀前瞻版下载v10.11.13.1 安卓版
下载
宝宝奇妙世界游戏手机版(宝宝巴士世界)下载v10.00.75.21 安卓最新版
下载
nba直播ios版下载v7.17.0 iphone版
下载