spring基础

spring概述

spring简介

  • Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益
  • Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架
  • 轻量——从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。
  • 控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它
  • 面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持
  • 容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用
  • 框架——Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你
  • spring优点
    • 1)方便解耦,简化开发:Spring 就是一个大工厂,可以将所有对象的创建和依赖关系的维护交给 Spring 管理
    • 2)方便集成各种优秀框架:Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如 Struts2、Hibernate、MyBatis 等)的直接支持
    • 3)降低 Java EE API 的使用难度:Spring 对 Java EE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等)都提供了封装,使这些 API 应用的难度大大降低
    • 4)方便程序的测试:Spring 支持 JUnit4,可以通过注解方便地测试 Spring 程序
    • 5)AOP 编程的支持:Spring 提供面向切面编程,可以方便地实现对程序进行权限拦截和运行监控等功能
    • 6)声明式事务的支持:只需要通过配置就可以完成对事务的管理,而无须手动编程

spring框架结构

在这里插入图片描述

  • Data Access/Integration(数据访问/集成)
    数据访问/集成层包括 JDBC、ORM、OXM、JMS 和 Transactions 模块,具体介绍如下。
    • JDBC 模块:提供了一个 JDBC 的抽象层,大幅度减少了在开发过程中对数据库操作的编码。
    • ORM 模块:对流行的对象关系映射 API,包括 JPA、JDO、Hibernate 和 iBatis 提供了的集成层。
    • OXM 模块:提供了一个支持对象/XML 映射的抽象层实现,如 JAXB、Castor、XMLBeans、JiBX 和 XStream。
    • JMS 模块:指 Java 消息服务,包含的功能为生产和消费的信息。
    • Transactions 事务模块:支持编程和声明式事务管理实现特殊接口类,并为所有的 POJO。
  • Web 模块
    Spring 的 Web 层包括 Web、Servlet、Struts 和 Portlet 组件,具体介绍如下。
    • Web 模块:提供了基本的 Web 开发集成特性,例如多文件上传功能、使用的 Servlet 监听器的 IoC 容器初始化以及 Web 应用上下文。
    • Servlet模块:包括 Spring 模型—视图—控制器(MVC)实现 Web 应用程序。
    • Struts 模块:包含支持类内的 Spring 应用程序,集成了经典的 Struts Web 层。
    • Portlet 模块:提供了在 Portlet 环境中使用 MV C实现,类似 Web-Servlet 模块的功能。
  • Core Container(核心容器)
    Spring 的核心容器是其他模块建立的基础,由 Beans 模块、Core 核心模块、Context 上下文模块和 Expression Language 表达式语言模块组成,具体介绍如下。
    • Beans 模块:提供了 BeanFactory,是工厂模式的经典实现,Spring 将管理对象称为 Bean。
    • Core 核心模块:提供了 Spring 框架的基本组成部分,包括 IoC 和 DI 功能。
    • Context 上下文模块:建立在核心和 Beans 模块的基础之上,它是访问定义和配置任何对象的媒介。ApplicationContext 接口是上下文模块的焦点。
    • Expression Language 模块:是运行时查询和操作对象图的强大的表达式语言。
  • 其他模块
    Spring的其他模块还有 AOP、Aspects、Instrumentation 以及 Test 模块,具体介绍如下。
    • AOP 模块:提供了面向切面编程实现,允许定义方法拦截器和切入点,将代码按照功能进行分离,以降低耦合性。
    • Aspects 模块:提供与 AspectJ 的集成,是一个功能强大且成熟的面向切面编程(AOP)框架。
    • Instrumentation 模块:提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用。
    • Test 模块:支持 Spring 组件,使用 JUnit 或 TestNG 框架的测试。

spring程序开发步骤

在这里插入图片描述

  • 导入spring开发的基本包坐标,编写Dao接口和实现类
  • 创建spring核心配置文件
  • 在spring配置文件中配置UserDaoImpl
  • 使用spring的api获得Bean实例

spring开发步骤demo

  • 配置Maven,新建spring项目
  • 编写简单UserDao接口
    package com.example.user;
    
    public interface UserDao {
        public void save();
    }
    
  • 实现UserDao接口
    package com.example.user;
    
    public class UserDaoImpl implements UserDao {
        @Override
        public void save() {
            System.out.println("save running");
        }
    }
    
  • 新建xml配置文件(applicationContext.xml),为实现类创建id标识
    <?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.example.user.UserDaoImpl"></bean>
    
    </beans>
    
  • 编写UserDaoTest类,进行测试。使用spring API(getBean)获得Bean实例,并调用UserDao的方法
    package com.example.user;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class UserDaoTest {
        @Test
        public void test() {
            ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
            UserDao userDao = (UserDao) app.getBean("userDao");
            userDao.save();
        }
    }
    

spring IoC容器

  • 控制反转思想(IoC) 是指在程序开发中,实例的创建不再由调用者管理,而是由 Spring 容器创建Spring 容器会负责控制程序之间的关系,而不是由程序代码直接控制,因此,控制权由程序代码转移到了 Spring 容器中,控制权发生了反转,这就是 Spring 的 IoC 思想
  • Spring 提供了两种 IoC 容器,分别为 BeanFactory 和 ApplicationContext

BeanFactory

  • BeanFactory 是基础类型的 IoC 容器,它由 org.springframework.beans.facytory.BeanFactory 接口定义,并提供了完整的 IoC 服务支持。简单来说,BeanFactory 就是一个管理 Bean 的工厂,它主要负责初始化各种 Bean,并调用它们的生命周期方法。
  • BeanFactory 接口有多个实现类,最常见的是 org.springframework.beans.factory.xml.XmlBeanFactory,它是根据 XML 配置文件中的定义装配 Bean 的。
  • 创建 BeanFactory 实例时,需要提供 Spring 所管理容器的详细配置信息,这些信息通常采用 XML 文件形式管理。其加载配置信息的代码具体如下所示:
    BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("D://applicationContext.xml"));
    

ApplicationContext

  • ApplicationContext 是 BeanFactory 的子接口,也被称为应用上下文。该接口的全路径为 org.springframework.context.ApplicationContext,它不仅提供了 BeanFactory 的所有功能,还添加了对 i18n(国际化)、资源访问、事件传播等方面的良好支持
  • ApplicationContext 接口有两个常用的实现类,具体如下
    • ClassPathXmlApplicationContext
      • 该类从类路径 ClassPath 中寻找指定的 XML 配置文件加粗样式,找到并装载完成 ApplicationContext 的实例化工作,具体如下所示
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(String configLocation);
        
    • FileSystemXmlApplicationContext
      • 该类从指定的文件系统路径中寻找指定的 XML 配置文件,找到并装载完成 ApplicationContext 的实例化工作,具体如下所示
        ApplicationContext applicationContext = new FileSystemXmlApplicationContext(String configLocation);
        
      • 它与 ClassPathXmlApplicationContext 的区别是:在读取 Spring 的配置文件时,FileSystemXmlApplicationContext 不再从类路径中读取配置文件,而是通过参数指定配置文件的位置,它可以获取类路径之外的资源,如“F:/workspaces/applicationContext.xml”
  • 在使用 Spring 框架时,可以通过实例化其中任何一个类创建 Spring 的 ApplicationContext 容器
  • 通常在 Java 项目中,会采用通过 ClassPathXmlApplicationContext 类实例化 ApplicationContext 容器的方式,而在 Web 项目中,ApplicationContext 容器的实例化工作会交由 Web 服务器完成。Web 服务器实例化 ApplicationContext 容器通常使用基于 ContextLoaderListener 实现的方式,它只需要在 web.xml 中添加如下代码:
    <!--指定Spring配置文件的位置,有多个配置文件时,以逗号分隔-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <!--spring将加载spring目录下的applicationContext.xml文件-->
        <param-value>
            classpath:spring/applicationContext.xml
        </param-value>
    </context-param>
    <!--指定以ContextLoaderListener方式启动Spring容器-->
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    
  • 需要注意的是,BeanFactory 和 ApplicationContext 都是通过 XML 配置文件加载 Bean 的
  • 二者的主要区别在于,如果 Bean 的某一个属性没有注入,则使用 BeanFacotry 加载后,在第一次调用 getBean() 方法时会抛出异常,而 ApplicationContext 则在初始化时自检,这样有利于检查所依赖的属性是否注入
  • 因此,在实际开发中,通常都选择使用 ApplicationContext,而只有在系统资源较少时,才考虑使用 BeanFactory

spring配置文件

Bean标签

  • 作为 Spring 核心机制的依赖注入,改变了传统的编程习惯,对组件的实例化不再由应用程序完成,转而交由 Spring 容器完成,在需要时注入应用程序中,从而对组件之间依赖关系进行了解耦。这一切都离不开 Spring 配置文件中使用的 <bean> 元素。
  • Spring 容器可以被看作一个大工厂,而 Spring 容器中的 Bean 就相当于该工厂的产品。如果希望这个大工厂能够生产和管理 Bean,这时则需要告诉容器需要哪些 Bean,以及需要以何种方式将这些 Bean 装配到一起
  • Spring 配置文件支持两种不同的格式,分别是 XML 文件格式和 Properties 文件格式
  • 通常情况下,Spring 会以 XML 文件格式作为 Spring 的配置文件,这种配置方式通过 XML 文件注册并管理 Bean 之间的依赖关系
  • XML 格式配置文件的根元素是 <beans>,该元素包含了多个 <bean> 子元素,每一个 <bean> 子元素定义了一个 Bean,并描述了该 Bean 如何被装配到 Spring 容器中
  • 默认情况下它调用的是类中的无参构造函数如果没有无参构造函数,则不能创建成功
  • 常用基本属性
    在这里插入图片描述
    • scope指对象的作用范围,取值如下
      • singleton:默认值,单例的。spring容器只生成一个Bean对象
        • 在spring核心xml文件被加载的时候,实例化一个Bean对象
        • 通常情况下,这种单例模式对于无会话状态的 Bean(如 DAO 层、Service 层)来说,是最理想的选择
        • Bean对象的生命周期
          • 对象创建:当容器加载,创建容器时,对象就创建了
          • 对象运行:只要容器在,对象一直存在
          • 对象销毁:当应用卸载,销毁容器时,对象就被销毁了
      • prototype:多例的。spring容器生成多个Bean对象。
        • Bean对象在每次调用getBean()方法时创建
        • 对需要保持会话状态的 Bean(如 Struts2 的 Action 类)应该使用 prototype 作用域
        • 生命周期:
          • 对象创建:当使用对象时,创建新的实例对象
          • 对象运行:只要对象在使用中,就一直活着
          • 对象销毁:当对象长时间不用,被Java的垃圾回收器回收
      • request:在一次 HTTP 请求中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Request 内有效
      • session:在一次 HTTP Session 中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Session 内有效
      • global session:在一个全局的 HTTP Session 中,容器会返回该 Bean 的同一个实例。该作用域仅在使用 portlet context 时有效
  • 其他属性
    • init-method:指定类中初始化方法名称
    • destroy-method:指定类中销毁方法名称
    • factory-bean:指定创建Bean对象的工厂
    • factory-method:指定实例化Bean对象的工厂方法
  • 引入其他配置文件:实际开发中,spring的配置内容非常多,这就导致spring配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,而在spring主配置文件通过import标签进行加载
    <import resource="applicationContext-xxx.xml"/>
    

依赖注入

  • 依赖注入(Dependency Injection,DI)和控制反转含义相同,Spring 容器在创建被调用者的实例时,会自动将调用者需要的对象实例注入给调用者,这样,调用者通过 Spring 容器获得被调用者实例,这称为依赖注入
  • Bean 的装配可以理解为依赖关系注入,Bean 的装配方式也就是 Bean 的依赖注入方式。Spring 容器支持多种形式的 Bean 的装配方式,如基于 XML 的 Bean 装配、基于 Annotation 的 Bean 装配和自动装配等
  • Spring 基于 XML 的装配通常采用两种实现方式,即设值注入(Setter Injection)和构造注入(Constructor Injection)。本节将讲解如何在 XML 配置文件中使用这两种注入方式
  • 在 Spring 实例化 Bean 的过程中,首先会调用默认的构造方法实例化 Bean 对象,然后通过 Java 的反射机制调用 setXxx() 方法进行属性的注入。因此,设值注入要求一个 Bean 的对应类必须满足以下两点要求
    • 必须提供一个默认的无参构造方法
    • 必须为需要注入的属性提供对应的 setter 方法
  • 使用设值注入时,在 Spring 配置文件中,需要使用 <bean> 元素的子元素 <property> 元素为每个属性注入值。而使用构造注入时,在配置文件中,主要使用 <constructor-arg> 标签定义构造方法的参数,可以使用其 value 属性(或子元素)设置该参数的值

注入数据类型

  • 注入数据的三种数据类型
    • 普通数据类型:使用Bean标签中value属性指定注入值
    • 引用数据类型:使用Bean标签中ref属性指定注入的引用类型
    • 集合数据类型:使用list、set、map、entry属性注入对应的集合类型

属性setter注入

  • IoC 容器使用 setter 方法注入被依赖的实例。通过调用无参构造器或无参 static 工厂方法实例化 bean 后,调用该 bean 的 setter 方法,即可实现基于 setter 的 DI
  • 代码demo
    • 定义UserService接口,方法为addUser
      package com.example.di;
      
      public interface UserService {
          public void addUser();
      }
      
    • 实现UserService接口,实现类名为UserServiceImpl,类中定义一个类型为UserDao的字段,依赖UserDao实例,并定义setter方法,用于依赖注入,然后实现了 UserService 接口的 addUser() 方法,并在方法中调用 UserDao的save()方法和输出一条语句
      package com.example.di;
      
      import com.example.user.UserDao;
      
      public class UserServiceImpl implements UserService{
          private UserDao userDao;
      
          public void setUserDao(UserDao userDao){
              this.userDao = userDao;
          }
          @Override
          public void addUser() {
              userDao.save();
              System.out.println("addUser running");
          }
      }
      
    • 在xml文件中配置信息,在 applicationContext.xml 配置文件中添加一个 <bean> 元素,用于实例化 UserServiceImpl 类,并将 UserDao 的实例注入到 userService 中,其实现代码如下所示:
      <bean id="userService" class="com.example.di.UserServiceImpl">
          <property name="userDao" ref="userDao"></property>
      </bean>
      
    • 定义SetterDiTest测试类,对上述setter DI代码进行测试
      package com.example.di;
      
      import org.junit.Test;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      public class SetterDiTest {
          @Test
          public void test(){
              ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
              UserService userService = (UserService) app.getBean("userService");
              userService.addUser();
          }
      }
      

构造方法注入

  • 指 IoC 容器使用构造方法注入被依赖的实例。基于构造器的 DI 通过调用带参数的构造方法实现,每个参数代表一个依赖
  • 代码Demo
    • 实现UserService接口,实现类名为UserServiceConstructDiImpl,类中定义一个类型为UserDao的字段,依赖UserDao实例,并定义参数类型为UserDao方法,用于依赖注入,然后实现了 UserService 接口的 addUser() 方法,并在方法中调用 UserDao的save()方法和输出一条语句
      package com.example.di;
      
      import com.example.user.UserDao;
      
      public class UserServiceConstructorDiImpl implements UserService{
          private UserDao userDao;
          public UserServiceConstructorDiImpl(UserDao userDao){
              this.userDao = userDao;
          }
      
          @Override
          public void addUser() {
              userDao.save();
              System.out.println("addUser running");
          }
      }
      
    • 在xml文件中配置信息,在 applicationContext.xml 配置文件中添加一个 <bean> 元素,用于实例化 UserServiceImpl 类,使用constructor-arg属性,将 UserDao 的实例注入到 UserServiceConstructorDiImpl 中,其实现代码如下所示:
      <bean id="userServiceConstructorDi" class="com.example.di.UserServiceConstructorDiImpl">
              <constructor-arg index="0" name="userDao" ref="userDao" type="com.example.user.UserDao">
              </constructor-arg>
          </bean>
      
    • 定义test类,对上述constructor DI代码进行测试:
      package com.example.di;
      
      import org.junit.Test;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      public class ConstructorDiTest {
          @Test
          public void test(){
              ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
              UserService userServiceConstructDi = (UserService) app.getBean("userServiceConstructorDi");
              userServiceConstructDi.addUser();
          }
      }
      

Bean实例化方法

默认无参构造

此种情况如上开发步骤demo所示,不再赘述。

静态工厂方法实例化

  • 静态工厂实例化demo
    • 定义工厂产品类Apple和Dog(忽略产品的实际意义和它们之间的关系)
      package com.example.factory;
      
      public class Apple {
          public Apple(){
              System.out.println("constructing apple");
          }
      }
      //------------------------------------------
      package com.example.factory;
      
      public class Dog {
          public Dog() {
              System.out.println("constructing dog");
          }
      }
      
    • 定义静态工厂类
      package com.example.factory;
      
      
      public class StaticBeanFactory {
          static public Dog getDog(){
              return new Dog();
          }
      
          static public Apple getApple(){
              return new Apple();
          }
      }
      
    • 配置xml文件,指定Apple类和Dog类的初始化方法为工厂方法
      <bean id="apple" class="com.example.factory.StaticBeanFactory" factory-method="getApple">
      </bean>
      <bean id="dog" class="com.example.factory.StaticBeanFactory" factory-method="getDog">
      </bean>
      
    • 定义测试类,测试静态工厂初始化代码
      package com.example.factory;
      
      import org.junit.Test;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      public class StaticBeanFactoryTest {
          @Test
          public void test(){
              ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
              Apple apple = (Apple) app.getBean("apple");
              Dog dog = (Dog) app.getBean("dog");
          }
      }
      

工厂实例方法实例化

  • 与静态工厂方法类似,不同之处在于,静态工厂方法不需要实例化工厂,而是直接调用其静态方法对Bean对象进行实例化。而工厂实例方法不包含静态方法,而是实例化工厂对象,通过对象调用类方法实例化Bean对象。

  • 通过以下demo可以更好体现它们的异同

    • 定义工厂方法类,仅是将静态工厂方法的静态方法设为非静态
      package com.example.factory;
      
      public class DynamicBeanFactory {
          public Dog getDog(){
              return new Dog();
          }
      
          public Apple getApple(){
              return new Apple();
          }
      }
      
    • 配置xml文件
      <!--    <bean id="apple" class="com.example.factory.StaticBeanFactory" factory-method="getApple">-->
      <!--    </bean>-->
      
      <!--    <bean id="dog" class="com.example.factory.StaticBeanFactory" factory-method="getDog">-->
      <!--    </bean>-->
      <bean id="dynamicFactory" class="com.example.factory.DynamicBeanFactory"></bean>
      <bean id="apple" factory-bean="dynamicFactory" factory-method="getApple"></bean>
      <bean id="dog" factory-bean="dynamicFactory" factory-method="getDog"></bean>
      
    • 定义测试类,测试结果
      package com.example.factory;
      
      import org.junit.Test;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      public class DynamicBeanFactoryTest {
          @Test
          public void test(){
              ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
              Apple apple = (Apple) app.getBean("apple");
      		Dog dog = (Dog) app.getBean("dog");
          }
      }
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值