Spring基础与进阶

Spring是一个轻量级的JavaEE开源框架,以其IoC容器和AOP支持著称。它提供了方便解耦、简化开发的能力,支持声明式事务处理,方便程序测试,并能与其他优秀框架如Struts、Hibernate集成。Spring的源码是Java设计模式的典范。文章详细介绍了Spring的体系结构,包括Bean的配置、作用域和生命周期,以及如何通过Spring进行快速开发。
摘要由CSDN通过智能技术生成

目录

01. Spring 简介

1.1 Spring 是什么

1.2 Spring 发展历程

1.3 Spring 的优势

1.3.1 方便解耦,简化开发

1.3.2 AOP 编程的支持

1.3.3 声明式事务的支持

1.3.4 方便程序的测试

1.3.5 方便集成各种优秀框架

1.3.6 降低 Java EE API 的使用难度

1.3.7 Java 源码是经典学习范例

1.4 Spring 的体系结构

02. Spring 快速入门

2.1 Spring 程序开发步骤

2.1.1 未使用 Spring 解耦之前的开发流程

2.1.2 使用 Spring 解耦之后的开发流程

2.1.3 Spring 程序开发步骤

03. Spring 配置文件

3.1 Bean 标签基本配置

3.2 Bean 标签范围配置

3.2.1 当 scope 的取值为 singleton 时

3.2.2 当 scope 的取值为 prototype 时

3.3 Bean 生命周期配置

3.3.1 方式一:

3.3.2 方式二:

3.4 Bean 实例化的三种方式

3.4.1 无参构造方法实例化

3.4.2 工厂静态方法实例化

3.4.3 工厂实例方法实例化

3.4.4 在实例工厂基础上的优化:使用FactoryBean

3.5 Spring 的重点配置

参考文献

持续更新......


01. Spring 简介

1.1 Spring 是什么

  • Spring 是分层的 Java SE/EE 应用 full-stack(全栈)轻量级开源框架,以 IoC(Inversion of Control:控制反转)和 AOP(Aspect Oriented Programming:面向切面编程)为内核。
注:
    轻量级:API 简单,学习成本低
    full-stack(全栈):在这儿指在各层都有对应的解决方案
    Web 层:Spring MVC
    DAO 层:JDBC 模板、Spring Data
  • Spring 提供了 展现层 Spring MVC持久层 Spring JDBC Template 以及 业务层事务管理 等众多的企业级应用技术,还能整合开源世界众多的著名的第三方框架和类库逐渐成为使用最多的 JAVA EE 企业级开源框架。

1.2 Spring 发展历程

1997 年,IBM 提出了 EJB 的思想。
1998 年,SUN 制定开发标准规范 EJB 1.0。
1999 年,EJB 1.1 发布。
2001 年,EJB 2.0 发布。
2003 年,EJB 2.1 发布。
2006 年,EJB 3.0 发布。
  • Rod Johnson(Spring 之父)
著作:
    Expert One-to-One J2EE Design and Development(2002)
    阐述了 J2EE 使用 EJB 开发设计的优点及解决方案。
    Expert One-to-One J2EE Development without EJB(2004)
    阐述了 J2EE 不使用 EJB 开发的解决方案(Spring 的雏形)
  • 2017 年 9 月份 发布了 Spring 的最新版本——Spring 5.0 通用版(GA)

1.3 Spring 的优势

1.3.1 方便解耦,简化开发

        通过 Spring 提供的 IoC(Inverse of Control)容器,可以将对象间的依赖交由 Spring 进行控制,避免硬编码所造成的过渡耦合。用户也不必再为 单例模式类、属性文件解析 等这些很底层的需求编写代码,可以更专注于上层的应用。

        粗略的DI入门案例如下:(项目创建在后序相关章节中不再讲述)

         注:properity中name属性名要与业务层中声明的BookDao类型变量名一致;ref属性名要与当前配置文件中dao的id名一致。

1.3.2 AOP 编程的支持

        通过 Spring 的 AOP 功能,方便进行 面向切面编程,许多不容易用传统 OOP(Object Oriented Programming:面向对象程序设计)实现的功能可以通过 AOP(Aspect Oriented Programming:面向切面编程/函数式编程)轻松实现。(通过 预编译方式运行期间动态代理 实现程序功能的统一维护的一种技术。AOP 是 OOP 的一种延续)

1.3.3 声明式事务的支持

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

1.3.4 方便程序的测试

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

1.3.5 方便集成各种优秀框架

        Spring 对各种优秀框架(Struts、Hibernate、Hessian、Quartz 等)的支持。

  • Struts:
Struts 是 Apache 软件基金会(ASF)赞助的一个 开源项目。他最初是 Jakarta 项目中的一个子项目,并在 2004 年 3 月成为 ASF 的顶级框架。它通过采用 Java Servlet / JSP 技术,实现了基于 Java EE Web 应用的 MVC(Model-View-Controller)设计模式的应用框架,是 MVC 经典设计模式中的一个经典产品。
Jakarta:开放源代码开发项目,受到 IBM 等公司在财力和技术上的鼎力支持。著名的 Tomcat 服务器 即出自 Jakarta 旗下。为方便管理,剥离 Tomcat、Lucene 等大型、成熟的子项目,成为相对独立的 Apache 子项目。
Jakarta 项目于 2011 年 12 月 21 日 退役,无剩余子项目。其独立的子项目包括:Ant、Avalon、Commons、DB、Excalibur、Gump、HiveMind、HttpComponents、James、Logging、Lucene、Maven、POI、Portals、Struts、Tapestry、Tomcat、Turbine、Velocity、Watchdog、BCEL、BSF、Cactus、ECS、JCS、JMeter、ORO、Regexp、Taglibs。
  • Hibernate:
Hibernate 是一个 开放源代码 的 对象关系映射 框架,它对 JDBC 进行了非常轻量级的对象封装,它将 POJO 与数据库表建立映射关系,是一个全自动的 ORM 框架,hibernate 可以自动生成 SQL 语句,自动执行,使得 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库。Hibernate 可以应用在任何使用 JDBC 场合,既可以在 Java 的客户端程序使用,也可以在 Servlet / JSP 的 Web 应用中使用,最具革命意义的是,Hibernate 可以在应用 EJB 的 Java EE 架构中取代 CMP,完成 数据持久化 的重任。
ORM(Object Relational Mapping:对象关系映射)框架采用 元数据 来描述对象与关系映射的细节,元数据一般采用 XML 格式,并且存放在专门的 对象-映射文件 中。简单理解为一种框架的格式。当前的 ORM 框架主要有五种:Hibernate(Nhibernate)、Ibatis、Mybatis、EclipseLink、JFinal。
CMP指令:CMP(Chip Multiprocessors:单芯片多处理器)指令是由美国斯坦福大学提出的,指 多核心 其思想是将大规模 并行处理器中的 SMP(对称多处理器)集成到统一芯片内,各个处理器 并行执行 不同的进程。与 CMP 比较,SMT 处理器结构 的 灵活性 比较突出。
  • Hessian:
Hessian 是一个轻量级的 remoting onHTTP 工具,使用简单的方法提供了 RMI 的功能。相比 WebService,Hessian更简单、快捷。采用的是二进制 RPC 协议,因为采用的是二进制协议,所以它很适合用于发送二进制数据。
  • Quartz:
Quartz 是 OpenSymphony 开源组织在 Job Scheduling 领域又一个开源项目,它可以与 J2EE 与 J2SE 应用程序相结合,也可以单独使用。Quartz 可以用来创建简单或为运行 十个、百个甚至是好几万个 Jobs 这样复杂的程序。Jobs 可以做成标准的 Java 组件或 EJBs。Quartz 最新版本为 Quartz 2.3.2。

1.3.6 降低 Java EE API 的使用难度

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

1.3.7 Java 源码是经典学习范例

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

1.4 Spring 的体系结构

02. Spring 快速入门

2.1 Spring 程序开发步骤

2.1.1 未使用 Spring 解耦之前的开发流程

com.itheima.dao.UserDaoImpl
    create 方法;
    delete 方法;
    update 方法;
    select 方法;
    
com.itheima.service.UserServiceImpl
    //通过 new 一个 UserDaoImpl 对象来使用
    UserDao userDao = new UserDaoImpl();

2.1.2 使用 Spring 解耦之后的开发流程

com.itheima.dao.UserDaoImpl
    create 方法;
    delete 方法;
    update 方法;
    select 方法;
    
XML 配置文件
    id 标识="com.itheima.dao.UserDaoImpl"
    
引入 Spring 框架
    读取 XML 配置文件;
    根据 id 标识 获取 全包名 / Bean 全限定名;
    根据 反射 创建 Bean 对象;
    返回对象。
    
com.itheima.service.UserServiceImpl
    //此时不需要再 new UserDaoImpl 对象,直接找 Spring 框架 要
    UserDao userDao = Spring 客户端.getBean( id 标识 )

2.1.3 Spring 程序开发步骤

  1. 导入 Spring 开发的基本包坐标spring-context
  2. 编写 Dao、Service 接口和实现类(创建Bean)
    public interface BookDao {
    	public void save();
    }
     
    public class BookDaoImpl implements BookDao {
    	public void save() {
    		System.out.println("book dao save ...");
    	}
    }
     
    public interface BookService {
    	public void save();
    }
     
    public class BookServiceImpl implements BookService {
    	private BookDao bookDao = new BookDaoImpl();
     
    	public void save() {
    		System.out.println("book service save ...");
    		bookDao.save();
    	}
    }
  3. 创建 Spring 核心配置文件(resources包下创建 Spring Config 类型文件名称为applicationContext.xml)
  4. 在 Spring 配置文件中配置 UserDaoImpl、UserServiceImpl(配Bean时一定要配接口的实现类!
    <bean id="bookDao" class="dao.impl.BookDaoImpl"/>
    <bean id="bookService" class="service.impl.BookServiceImpl"/>
  5. 使用 Spring 的 API 获得 Bean 实例(创建ApplicationContext对象并getBean)
    public static void main(String[] args) {
    //获取IOC容器
    //1.加载类路径下的配置文件,默认为立即加载。new的是AC接口的实现类
        ApplicationContext ctx = new
            ClassPathXmlApplicationContext("applicationContext.xml");
    //2.从文件系统下加载配置文件
        //ApplicationContext ctx = new FileSystemXmlApplicationContext("绝对路径");
            
    //3.已过时,延迟加载
        //Resource resources = new ClassPathResource("applicationContext.xml");
        //BeanFactory bf = new XmlBeanFactory(resources);
    
    //获取Bean
    //法一:注意此处需要强转
        //BookService bookService = (BookService) ctx.getBean("bookService");
    //法二:
        //BookService bookService =  ctx.getBean("bookService",bookDao.class);
    //法三:
        BookService bookService =  ctx.getBean(bookDao.class);
        bookService.save();
    }
注:
    Dao层:DAO(Data Access Object:数据访问对象)是一个面向对象的数据库接口,它显露了 Microsoft Jet 数据库引擎(由 Microsoft Access 所使用),并允许 Visual Basic 开发者通过 ODBC 像直接连接到其他数据库一样,直接连接到 Access 表。DAO 最适用于单系统应用程序或小范围本地分布使用。
    ODBC(Open Database Connectivity:开放数据库连接)是为解决 异构数据库 间的数据共享而产生的,现已成为 WOSA(The Windows Open System Architecture:Windows 开放系统体系结构)的主要部分和基于 Windows 环境的一种数据库访问接口标准。ODBC 为异构数据库访问提供统一接口,允许应用程序以 SQL 为数据存取标准,存取不同 DBMS(DataBase Management System:数据库管理系统)管理的数据;使应用程序直接操纵 DB(DataBase)中的数据,免除随 DB 的改变而改变。用 ODBC 可以访问各类计算机上的 DB 文件,甚至访问如 Excel 表和 ASCII 数据文件这类非数据库对象。

03. Spring 配置文件

3.1 Bean 标签基本配置

  •  用于配置对象交由 Spring 来创建
  • 默认情况下它( Spring ) 调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功
  • 适合交给容器进行管理的Bean:表现层、业务层、数据层、工具
  • 不适合交给容器进行管理的Bean:封装实体的域对象
基本属性:
    id:Bean 实例在 Spring 容器中的唯一标识
    name:定义bean的别名,若定义多个则用","or";"or" "分割
    class:Bean 的 全限定名称 / 全包名

3.2 Bean 标签范围配置

  • scope:指对象的作用范围,取值如下:
取值范围说明
singleton默认值,单例的
prototype多例的,原型模式
requestWeb 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中
sessionWeb 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中
global session

Web 项目中,应用在 Portlet 环境,如果没有 Portlet 环境,那么 globalSession 相当于 Session

3.2.1 当 scope 的取值为 singleton 时

Bean 的实例化个数:1 个
Bean 的实例化时机:当 Spring 核心文件被加载时,实例化配置的 Bean 实例
<bean id="userDaoScopeSingleton" class="com.itheima.dao.impl.UserDaoImpl" scope="singleton"></bean>

Bean 的生命周期:

  • 对象创建:当应用加载,创建容器时,对象就被创建了
  • 对象运行:只要容器在,对象就一直活着
  • 对象销毁:当应用卸载,销毁容器时,对象被销毁

3.2.2 当 scope 的取值为 prototype 时

Bean 的实例化个数:多个 / 有几个对象就实例化几次
Bean 的实例化时机:当调用 getBean() 方法时 实例化 Bean
<bean id="userDaoScopePrototype" class="com.itheima.dao.impl.UserDaoImpl" scope="prototype"></bean>

Bean 的生命周期:

  • 对象创建:当使用对象时,创建新的对象实例
  • 对象运行:只要对象在使用中,就一直活着
  • 对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收

3.3 Bean 生命周期配置

 

  • init-method:指定类中的初始化方法名称
  • destory-method:指定类中销毁方法名称

3.3.1 方式一:

package com.itheima.dao;
public interface UserDao {}
package com.itheima.dao.impl;
import com.itheima.dao.UserDao;
public class UserDaoImpl implements UserDao {
    public void init(){
        System.out.println("Dao ------ 初始化方法......");
    }
    public void destroy(){
        System.out.println("Dao ------ 销毁方法......");
    }
}
<?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">
    <bean id="userDaoInitAndDestroy" class="com.itheima.dao.impl.UserDaoImpl" init-method="init" destroy-method="destroy"></bean>
</beans>
@Test
public void springBeanInitAndDestroyTest(){
    //该类是AC类的子类,实现了容器关闭相关函数
    ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    System.out.println(app.getBean("userDaoInitAndDestroy"));
    // ctx.close(); close方法比较暴力,我们在这里可以采用注册关闭钩子
    ctx.registerShutdownHook();
}

3.3.2 方式二:

        修改BookServiceImpl类,删除原来的自定义save()、destroy(),添加InitializingBean,DisposableBean接口并实现其中的两个方法afterPropertiesSet和destroy,这样可以在bean配置中删除init-method和destroy-method。

public class BookServiceImpl implements BookService, InitializingBean,
DisposableBean {
    private BookDao bookDao;
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
    public void destroy() throws Exception {
        System.out.println("service destroy");
    }
    public void afterPropertiesSet() throws Exception {
        System.out.println("service init");
    }
}

3.4 Bean 实例化的三种方式

3.4.1 无参构造方法实例化

        注:此处若把无参构造方法修改为private类型,依然能正常实例化,因为底层使用了暴力反射机制。

package com.itheima.dao;
public interface UserDao {}
package com.itheima.dao.impl;
import com.itheima.dao.UserDao;
public class UserDaoImpl implements UserDao {
    public UserDaoImpl(){
        System.out.println("Dao ------ 无参构造方法......");
    }
}
<?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">
    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"></bean>
</beans>
@Test
public void springProxyTest(){
    ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserDao userDao = (UserDao) app.getBean("userDao");
    System.out.println(userDao);
}

3.4.2 工厂静态方法实例化

//静态工厂创建对象
public class OrderDaoFactory {
    public static OrderDao getOrderDao(){
        System.out.println("factory setup....");
        return new OrderDaoImpl();
    }
}

        注:一定要指定静态工厂中的真正用来造orderDao对象的方法factory-method!

<bean id="orderDao" class="factory.OrderDaoFactory" factory-method="getOrderDao"/>
/*
早期直接在普通类的main函数中启动运行
*/
public class App {
    public static void main() {
        OrderDao orderDao = OrderDaoFactory.getOrderDao();
        System.out.println(orderDao);
    }
}
/*
使用spring方式
*/
@Test
public void springProxyTest(){
    ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
    OrderDao orderDao = (OrderDao) app.getBean("orderDao");
    System.out.println(orderDao);
}

3.4.3 工厂实例方法实例化

public class UserDaoFactory {
    public UserDao getUserDao(){
        return new UserDaoImpl();
    }
}
//工厂类
//注意由于工厂中的方法非静态,应先造出工厂对象
<bean id="userFactory" class="factory.UserDaoFactory"/>
 
<bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
public class App {
    public static void main() {
        /*
        早期创建对象方式
        */
        //创建实例工厂对象
        UserDaoFactory userDaoFactory = new UserDaoFactory();
        //通过实例工厂对象创建对象
        UserDao userDao = userDaoFactory.getUserDao();
        sout(userDao);

        /*
        使用spring
        */
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (OrderDao) ctx.getBean("userDao");
        System.out.println(userDao);
    }
}
/*
使用spring
*/

        注:会发现,在这第三种方式中,id名为userFactory的这个bean只是配合使用的,实际无意义;并且factory-method不固定,每次都需要配置。对于诸如此类的问题,可以进行如下的改良。

3.4.4 在实例工厂基础上的优化:使用FactoryBean

public class UserDaoFactoryBean implements FactoryBean<UserDao> {
    //代替原始实例工厂中创建对象的方法
    public UserDao getObject() throws Exception {
        return new UserDaoImpl();
    }
    //返回所创建类的Class对象
    public Class<?> getObjectType() {
        return UserDao.class;
    }
}
<bean id="userDao" class="factory.UserDaoFactoryBean"/>

        注:此UserDaoFactoryBean的bean造出来的对象是上面UserDaoFactoryBean类中getObject()方法所造的对象UserDaoImpl!

        除此之外,FactoryBean接口还有其他的方法,例如单例控制:

T getObject() throws Exception;
Class<?> getObjectType();
default boolean isSingleton() {
    return true;
}

3.5 Spring 的重点配置

<beans>
    <bean>    标签
        id 属性:在容器中 Bean 实例的唯一标识,不允许重复
        class 属性:要实例化的 Bean 的全限定名
        scope 属性:Bean 的作用范围,常用是 singleton(单例模式)和 prototype(原型模式/多例模式)
        <property>    标签:属性注入
            name 属性:属性名称
            value 属性:注入的普通属性值
            ref 属性:注入的对象引用值
            <list>标签
                <value>value</value>
            </list>
            <map>标签(key 和 value)
                <entry key="key" value-ref="value-ref"></entry>
            </map>
            <properties>标签(key 和 value 均为 字符串)
                <props><prop key="key">value</prop></props>
            </properties>
        </property>
        <constructor-arg>有参结构体 set 注入 标签</constructor-arg>
        <constructor-arg name="userDao" ref="set 方法 - set 转 小驼峰"></constructor-arg>
    </bean>
    <import>标签:导入其他的 Spring 的分文件</import>
    <import resource="applicationContext-user.xml"></import>
</beans>

3.6 Bean的依赖注入

3.6.1 setter注入

3.6.2 构造器注入


参考文献

......

        本文仅用作个人学习总结和博客试写,在参考文献的基础上投入了大量劳动和原创内容总结,保证尊重原作者的合法权益,如有不妥请与我联系。


持续更新......

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清风微浪又何妨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值