• 阶段七-Day01-Spring01


    一、Spring框架介绍

    1. 介绍

    Spring Framework是由Spring团队研发的模块化、轻量级开源框架。其主要目的是为了简化项目开发。

    Spring Framework前身是interface21,由Rod Johnson于2002年研发,主要是为了不使用EJB下依然能够构建高质量Java EE项目。EJB是当年横行一时的Java EE框架,目前已经属于淘汰技术。

    2. 发展历史

    • 2002年,大约有3万行代码的interface21出现。

    • 2003年,Rod Johnson和朋友在interface21基础上研发了Spring。

    • 2004年3月,Spring 1.0发布。

    • 2006年10月,Spring 2.0发布。

    • 2007年11月,更名为 SpringSource,同时发布了 Spring 2.5。

    • 2009年12月,Spring 3.0 发布。同时把Spring由一个jar包拆分成多个jar包,真正实现模块化

    • 2013年12 月,Spring 框架 4.0发布。

    • 2017年9月,Spring框架5.0发布。

    暂时使用Spring框架版本5.3.16。

    3. Spring各个模块

    Test

    对应spring-test.jar。Spring提供的测试工具,可以整合JUnit测试,简化测试环节。

    Core Container

    Spring的核心组件, 包含了Spring框架最基本的支撑。

    Beans, 对应spring-beans.jar。Spring进行对象管理时依赖的jar包。

    Core, 对应spring-core.jar,Spring核心jar包。

    Context, 对应spring-context.jar, Spring容器上下文对象。

    SpEL, 对应spring-expression.jar, Spring表达式语言。

    AOP

    面向切面编程,对应spring-aop.jar。

    Aspects

    Aspects的具体实现为面向切面编程的另一种实现。对应spring-aspects.jar。

    Instrumentation

    服务器代理接口的具体实现。对应spring-instrument.jar。

    Messaging

    集成messaging api和消息协议提供支持。对应spring-messaging.jar。

    Data Access/Integration

    Spring对数据访问层的封装。

    JDBC,对应spring-jdbc.jar。Spring对jdbc的封装,当需要使用spring连接数据库时使用spring-jdbc.jar需要依赖spring-tx.jar。

    Transactions。对应spring-tx.jar,事务管理。

    ORM,对应spring-orm.jar。 spring整合第三方orm框架需要使用的jar包,例如Hibernate框架.

    Web

    Spring对javax下的接口或类做的扩展功能。

    spring-web.jar。对Servlet,Filter,Listener等做的增强。

    spring-webmvc.jar,实际上就是SpringMVC框架.。需要依赖spring环境和spring-web.jar。

    二、Spring IoC/DI 介绍

    1. Spring IoC/DI(常见面试题)

    IoC(Inversion of Control) 控制反转

    DI(dependency injection) 依赖注入

    IoC/DI指的是一个过程:对象的创建仅仅通过Spring容器负责,Spring容器可以通过对象的构造方法或工厂方法进行实例化对象。在创建对象过程中,如果对象需要依赖其他对象也可以直接在Spring容器中注入到当前对象。

    2. 专业术语介绍

    • 容器(Container):放置所有被管理的对象(所有的Bean)。其本质是在容器对象里面有一个全局Map对象,map对象中放置所有被管理的对象。Spring中容器是指ApplicationContext接口及子接口或实现类。

    • beans:容器中所有被管理的对象称为beans。如果单说其中一个对象可称为bean。

    3. IoC/DI的好处

    Spring IoC/DI使用后可以管理项目中相关对象,让对象管理的事情和业务分离(解耦)。同时程序员也不需要管理对象的依赖关系,所有的依赖关系交给Spring容器进行管理。

    4. IoC/DI具体应用场景

    IoC/DI 主要作用就是管理对象的实例化和对象之间依赖关系。项目中以前需要自己实例化的层对象、框架或工具包的入口类都可以交给Spring 容器进行管理。

    • 层对象:PeopleMapper 接口代理对象、PeopleServiceImpl。

    • 框架入口类:SqlSessionFactory等。

    三、第一个Spring项目

    Spring框架不依赖于Servlet容器(Tomcat),所以普通Java项目就可以使用Spring框架。

    Spring框架提供了XML、注解、Java Config三种方式进行使用。

    1. 创建项目,并添加依赖

    在项目的pom.xml中添加Spring项目的最基本依赖。

    Spring项目想要运行起来必须包含:

    • spring-context.jar。spring上下文依赖,它依赖了下面的四个jar。

      • spring-core.jar。Spring 核心jar包。它依赖了spring-jcl.jar。

      • spring-aop.jar。Spring AOP基本支持。

      • spring-expression.jar。Spring的表达式语言支持。

      • spring-beans.jar。Spring容器的bean 管理。

      • spring-jcl.jar。Spring 4版本时是common-logging.jar。从5开始Spring自己对日志进行了封装spring-jcl.jar。

    所以在Maven中想要使用Spring框架只需要在项目中导入spring-context就可以了,其他的jar包根据Maven依赖传递性都可以导入进来。

    1. <dependencies>
    2. <dependency>
    3. <groupId>org.springframeworkgroupId>
    4. <artifactId>spring-contextartifactId>
    5. <version>5.3.16version>
    6. dependency>
    7. dependencies>

    2. 随意创建一个类

    1. package com.sh.pojo;
    2. public class Emp {
    3. private int id;
    4. private String name;
    5. private String addr;
    6. @Override
    7. public String toString() {
    8. return "Emp{" +
    9. "id=" + id +
    10. ", name='" + name + '\'' +
    11. ", addr='" + addr + '\'' +
    12. '}';
    13. }
    14. public int getId() {
    15. return id;
    16. }
    17. public void setId(int id) {
    18. this.id = id;
    19. }
    20. public String getName() {
    21. return name;
    22. }
    23. public void setName(String name) {
    24. this.name = name;
    25. }
    26. public String getAddr() {
    27. return addr;
    28. }
    29. public void setAddr(String addr) {
    30. this.addr = addr;
    31. }
    32. public Emp(int id, String name, String addr) {
    33. this.id = id;
    34. this.name = name;
    35. this.addr = addr;
    36. }
    37. public Emp() {
    38. }
    39. }

    3. 创建Spring配置文件

    在src/main/resources下新建spring-config.xml文件。

    小提示:

    文件名称没有强制要求。官方示例中配置文件名称叫做applicationContext.xml

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans
    5. https://www.springframework.org/schema/beans/spring-beans.xsd">
    6. <bean id="emp01" class="com.sh.pojo.Emp">bean>
    7. beans>

    4. 创建测试类

    创建测试类,测试Spring功能。

    1. @Test
    2. public void test(){
    3. //加载配置文件
    4. ApplicationContext ac = new ClassPathXmlApplicationContext("spring-config01");
    5. //获取bean对象中的实例对象
    6. Object emp01 = ac.getBean("emp01");
    7. System.out.println(emp01);
    8. }

    四、Bean实例化的两种方式(面试题)

    在Spring中实例化Bean有两种方式:

    • 通过构造方法进行实例化。默认使用无参构造。这种方式和以前new的方式是等效的。上面的第一个Spring项目其实就是这种,只需要在XML中通过的class属性指定类的全限定路径,然后就可以实例化对象。

    • 通过工厂进行实例化。可以通过静态工厂和实例工厂进行实例化。这种方式完全是根据设计模式中工厂模式的思想而研发出的。Spring考虑到如果需要频繁实例化某个类的对象,工厂模式无疑是一个好选择。

    上面第一个Spring项目已经演示过第一种实例化Bean的方式,所以下面重点演示使用工厂进行实例化bean。

    1. 使用实例工厂实例化bean

    1.1 创建工厂类

    实例工厂方式需要实例化工厂类。所以工厂中创建bean的方法是一个实例方法。

    在项目中创建实例工厂类,并编写方法返回创建的实例对象。

    1. package factory;
    2. import com.sh.pojo.Emp;
    3. public class EmpFactory {
    4. Emp emp = new Emp();
    5. public Emp getInstance(){
    6. return emp;
    7. }
    8. }
    1.2 配置配置文件

    在applicationContext.xml中先配置工厂实例,然后通过工厂实例产生自己想要的bean对象,注意bean标签中属性含义:

    • factory-bean:工厂bean的id属性值。

    • factory-method:工厂中创建bean的方法。

    1. <bean id="factory" class="com.sh.factory.EmpFactory"/>
    2. <bean id="emp02" factory-bean="factory" factory-method="getInstance">bean>
    1.3 在测试类中测试效果

    2. 使用静态工厂实例化bean

    2.1 创建工厂类

    静态工厂和实例工厂类最主要的区别是,创建bean的方法是static修饰的。

    1. package com.sh.factory;
    2. import com.sh.pojo.Emp;
    3. public class StaticEmpFactory {
    4. //创建静态对象
    5. private static Emp emp = new Emp();
    6. //使用静态方法
    7. public static Emp getInstance(){
    8. return emp;
    9. }
    10. }
    2.2 配置配置文件

    在applicationContext.xml中配置bean,注意bean标签中属性含义:

    • class:静态工厂类的全限定路径

    • factory-method:静态工厂中创建bean的静态方法。

    1. <bean id="emp03" class="com.sh.factory.StaticEmpFactory" factory-method="getInstance">bean>

    五、属性注入的两种方式(较常见面试题)

    Spring中给Bean属性赋值有两种方式:

    • 构造注入(Constructor-based Dependency Injection):通过构造方法给bean的属性赋值。所以要求bean的类中必须提供对应参数的构造方法。相当于以前创建对象时new People(1,"张三");

    • 设值注入,又称setter注入(Setter-based Dependency Injection):通过Bean的set方法赋值。所以要求Bean中属性必须提供set方法。相当于以前的:People peo = new People(); peo.setId(1); peo.setName("张三");

    1. 构造注入

    • 调用有参构造方法创建对象及完成属性值的注入,必须提供有参构造方法。

    • 提供了有参构造方法,不再默认提供无参构造方法,不使用构造注入会需要使用无参构造方法创建对象,需要提供无参构造方法。

    1.1 检查Bean类中是否有有参构造方法
    1.2 配置bean

    在配置文件applicationContext.xml中可以通过的子标签设置构造方法中一个参数的值。

    解释说明:

    constructor-arg 里面有5个属性,这5个属性分为2类。

    (1)用来确定给哪个属性进行赋值

    name:参数名称。

    index:参数索引。从0开始算起。

    type:参数类型。8大基本数据类型可以直接写关键字。其他类型需要写类型的全限定路径。

    这三个属性如果用一个就能精确的告诉Spring,要设置的构造方法参数是哪个,可以使用一个。如果无法精确到某个构造方法参数,可以多个一起结合使用。

    (2)设置属性的值

    value:简单数据类型直接设置。Spring会自动进行类型转换。

    ref:需要引用另一个bean的id。也就是说这个参数是一个引用类型,且这个类的对象也被Spring容器管理。

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans
    5. https://www.springframework.org/schema/beans/spring-beans.xsd">
    6. <bean id="emp" class="com.sh.pojo.Emp">
    7. <constructor-arg name="id" value="1"/>
    8. <constructor-arg name="name" value="zs"/>
    9. <constructor-arg name="addr" value="北京"/>
    10. bean>
    11. beans>

    2. 设值注入(setter注入)

    • 调用set方法完成属性值的注入,必须提供set方法。

    • Setter注入一般都是结合无参构造方法一起使用。所以类中有无参构造方法和set方法。

    2.1 配置bean

    使用属性property

    1. <bean id="emp1" class="com.sh.pojo.Emp">
    2. <property name="id" value="2"/>
    3. <property name="name" value="zs"/>
    4. <property name="addr" value="上海"/>
    5. bean>
    2.2 其它引用数据类型的属性注入

    无论是构造注入还是设值注入都提供了value和ref进行设置值。这两个属性只能给属性赋予简单数据类型或其他bean的引用。

    如果类的属性是数组、集合等类型需要通过下面方式进行设置。

    一旦使用了下面子标签方式,就不能对设置value属性或ref属性。

    2.1.1 Set类型
    2.2.2 List类型
    2.2.3 Array类型
    2.2.4 Map类型
    2.2.5 Null值类型
    2.2.6 引用其他Bean

    如果需要引用其他Bean,直接在property标签中使用ref引用就可以。使用子标签ref也可以,但是没有直接用ref属性的方式简单。

    3. 构造注入和设值注入的混合使用

    也可以让构造注入和设值注入混合使用。这两种方式只要保证有对应的有参构造方法和setter方法,就可以使用其中一种方式设置部分属性的值。

    配置文件设置

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    5. <bean id="people01" class="com.sh.pojo.People">
    6. <property name="id" value="1"/>
    7. <property name="name" value="zs"/>
    8. <property name="list">
    9. <list>
    10. <value>1value>
    11. <value>1value>
    12. <value>1value>
    13. <value>1value>
    14. list>
    15. property>
    16. <property name="set">
    17. <set>
    18. <value>1value>
    19. <value>1value>
    20. <value>1value>
    21. <value>1value>
    22. set>
    23. property>
    24. <property name="map">
    25. <map>
    26. <entry key="a" value="a">entry>
    27. <entry key="b" value="b">entry>
    28. <entry key="c" value="c">entry>
    29. map>
    30. property>
    31. <property name="ints">
    32. <array>
    33. <value>1value>
    34. <value>1value>
    35. <value>1value>
    36. array>
    37. property>
    38. <property name="emp" ref="emp">property>
    39. bean>
    40. <bean id="emp" class="com.sh.pojo.Emp">bean>
    41. beans>

    六、自动注入

    1. 属性值自动注入

    小提示:

    自动注入指的都是bean之间的自动注入。能够自动注入必须保证Spring 容器中包含能被自动注入的bean。

    在Spring中,允许Bean的自动注入,有两种方式进行配置。

    • 在根标签中配置default-autowire属性,自动注入的策略,可取值有5个。

      1. default:默认值,不自动注入。(使用在bean标签中有其它含义)

      2. no:不自动注入。

      3. byName:

        1. 通过名称自动注入。名称:属性名与bean的id属性值。

        2. 会自动寻找容器中与注入值属性名同名的id属性值的bean进行注入。

        3. 底层为setter注入,设值注入。

      4. byType:

        1. 通过类型自动注入。类型:属性类型与bean的class类型。

        2. 会自动寻找容器中与注入值类型相同的bean进行注入。如果有多个相同类型的bean注入会出现异常。

        3. 底层为setter注入,设值注入。

      5. constructor:

        1. 通过构造方法进行注入。调用有参构造方法完成对象创建及属性自动注入。

        2. 寻找bean的有参构造方法中只包含需要注入属性参数的构造方法。自动属性注入。

        3. 底层为构造注入。

    配置文件

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
    5. default-autowire="constructor"
    6. >
    7. <bean id="cat" class="com.sh.pojo.Cat">bean>
    8. <bean id="animal" class="com.sh.pojo.Animal" >
    9. bean>
    10. beans>
    • 标签中配置autowire属性,和default-autowire取值相同。

      • default:使用上级标签的default-autowire属性值。

      • default-autowire表示全局的配置。如果autowire和default-autowire同时存在,autowire生效。即局部的优先级高

    七、bean标签的scope属性(面试题)

    Spring中的scope控制的是Bean的有效范围。

    一共有6个可取值,官方截图如下:

    singleton:默认值。bean是单例的,每次获取Bean都是同一个对象。(单例设计模式)

    prototype:bean时原型的,每次获取bean都重新实例化。

    request:每次请求重新实例化对象,同一个请求中多次获取时单例的。

    session:每个会话内bean是单例的。

    application:整个应用程序对象内bean是单例的。

    websocket:同一个websocket对象内对象是单例的。

    里面的singleton和prototype在Spring最基本的环境中就可以使用,不需要web环境。

    但是里面的request、session、application、websocket都只有在web环境才能使用。

    衍生问题:Spring 中 Bean是否是线程安全的?

    1. 如果bean的scope是单例的,bean不是线程安全的。

    2. 如果bean的scope是prototype,bean是线程安全的。

    <bean id="people" class="com.sh.pojo.People" scope="singleton">bean>

    八、单例设计模式(面试中笔试题)

    设计模式:根据面向对象五大设计思想衍生出的常见23种设计模式,每种写法可以专门解决一类问题。

    单例设计模式:保证某个类在整个应用程序中只有一个对象。

    单例写法分为两种:饿汉式、懒汉式。

    重要提示:

    单例设计模式必须达到用纸手写的能力。

    1. 饿汉式

    1. //单例设计模式 - 饿汉式
    2. public class SingletonHungry {
    3. //因为是单例,要设置为静态对象,只创建一次
    4. private static SingletonHungry s = new SingletonHungry();
    5. public SingletonHungry() {
    6. }
    7. //提供静态方法返回对象
    8. public static SingletonHungry getInstance(){
    9. return s;
    10. }
    11. }

    2. 懒汉式

    1. package com.sh.util;
    2. //单例设计模式 - 懒汉式
    3. public class SingletonLazy {
    4. private static SingletonLazy s;
    5. //在方法被调用的时候才创建对象
    6. public static SingletonLazy getInstance(){
    7. //为了使线程安全,要加锁
    8. //使用双重检查锁DCL(Double Check Lock双端检锁)
    9. //但是双重检查锁DCL(Double Check Lock双端检锁)也不一定是线程安全的
    10. //因为有指令重排
    11. //必须关闭指令重排才能解决线程安全问题
    12. //可以使用volatile关键字来避免此问题。
    13. //private static volatile SingletonLazy instance = null;
    14. if (s == null){
    15. synchronized (SingletonLazy.class){
    16. //解决多线程重复创建对象,里面还需要再次判断
    17. if (s == null){
    18. s = new SingletonLazy();
    19. return s;
    20. }
    21. }
    22. }
    23. return s;
    24. }
    25. }

    九、Spring 循环注入问题(面试题)

    1. 概念

    循环注入即多个类相互依赖,产生了一个闭环。

    2. 官方解释

    在Spring IoC/DI使用过程中,可能出现循环注入的情况。

    当两个类都是用构造注入时,没有等当前类实例化完成就需要注入另一个类,而另一个类没有实例化完整还需要注入当前类,所以这种情况是无法解决循环注入问题的的。会出现BeanCurrentlyInCreationException异常。

    3. 循环依赖的场景

    原因:

    单例的setter注入: 

    4. 解决循环依赖

    如果两个类都使用设值注入且scope为singleton的就不会出现问题,可以正常执行。因为单例默认下有三级缓存(DefaultSingletonBeanRegistry),可以暂时缓存没有被实例化完成的Bean。

    4.1 单例模式创建对象的步骤

    Spring的单例对象的初始化主要分为三步:

    1. 实例化:其实也就是调用对象的构造方法实例化对象。

    2. 注入:填充属性,这一步主要是对bean的依赖属性进行填充。

    3. 初始化:属性注入后,执行自定义初始化操作。

    4.2 循环依赖问题

    A的某个field依赖了B的实例对象,同时B的某个field依赖了A的实例对象,这种情况为循环依赖。

    4.3 解决循环依赖
    • 一级缓存(singletonObjects):存放实例化,属性注入,初始化完成的对象。

    • 二级缓存(earlySingletonObjects):存放早期暴露出来的Bean对象,属性还未填充完整。

    • 三级缓存(singletonFactories):存放bean创建工厂,以便于后面扩展有机会创建代理对象。

            二级缓存就可以解决简单的循环依赖,三级缓存是为了提高拓展性

    十、BeanFactory和ApplicationContext(经典面试题)

    1. BeanFactory接口

    BeanFactory是Spring中的顶级接口,接口中定了Spring容器最基本功能。是Spring IoC的最核心接口。

    1. DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    2. XmlBeanDefinitionReader xbdr = new XmlBeanDefinitionReader(factory);
    3. xbdr.loadBeanDefinitions(new FileSystemResource("C:\IdeaWS\spring_day01\src\main\resources\application.xml"));
    4. Object teacher = factory.getBean("teacher");

    BeanFactory是在调用getBean方法的时候才实例化Bean。(懒汉式)

    2. ApplicationContext接口

    ApplicationContext是BeanFactory的子接口。所以要比BeanFactory的功能更加强大,除了BeanFactory的功能,还包含了:

    • AOP 功能

    • 国际化(MessageSource)

    • 访问资源,如URL和文件(ResourceLoader)

    • 消息发送机制(ApplicationEventPublisher)

    • Spring集成Web时的WebApplicationContext

    在使用时ApplicationContext时多使用ClassPathXmlApplicationContext

    1. ApplicationContext applicationContext =
    2. new ClassPathXmlApplicationContext("applicationContext.xml");
    3. Object teacher = applicationContext.getBean("teacher");

    ApplicationContext是在加载配置文件后立即实例化Bean。(饿汉式)

    可以通过bean标签的lazy-init属性进行控制,让bean懒加载。

    十一、Spring整合MyBatis(非web环境)

    1. 创建项目并添加依赖

    创建一个普通Maven项目,并在pom.xml中添加依赖

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0modelVersion>
    5. <groupId>com.shgroupId>
    6. <artifactId>Spring02artifactId>
    7. <version>1.0-SNAPSHOTversion>
    8. <dependencies>
    9. <dependency>
    10. <groupId>org.springframeworkgroupId>
    11. <artifactId>spring-contextartifactId>
    12. <version>5.3.16version>
    13. dependency>
    14. <dependency>
    15. <groupId>org.mybatisgroupId>
    16. <artifactId>mybatis-springartifactId>
    17. <version>2.0.7version>
    18. dependency>
    19. <dependency>
    20. <groupId>org.mybatisgroupId>
    21. <artifactId>mybatisartifactId>
    22. <version>3.5.9version>
    23. dependency>
    24. <dependency>
    25. <groupId>mysqlgroupId>
    26. <artifactId>mysql-connector-javaartifactId>
    27. <version>8.0.28version>
    28. dependency>
    29. <dependency>
    30. <groupId>junitgroupId>
    31. <artifactId>junitartifactId>
    32. <version>4.12version>
    33. <scope>testscope>
    34. dependency>
    35. dependencies>
    36. project>

    2. 创建Spring配置文件

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    5. <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    6. <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    7. <property name="url" value="jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true"/>
    8. <property name="username" value="root"/>
    9. <property name="password" value="root"/>
    10. bean>
    11. <bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    12. <property name="dataSource" ref="dataSource"/>
    13. <property name="typeAliasesPackage" value="com.sh.pojo"/>
    14. bean>
    15. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    16. <property name="basePackage" value="com.sh.mapper"/>
    17. <property name="sqlSessionFactoryBeanName" value="SqlSessionFactory"/>
    18. bean>
    19. beans>

    3. 创建实体类

    创建com.sh.pojo.User

    1. package com.sh.pojo;
    2. import java.io.Serializable;
    3. public class User implements Serializable {
    4. private int id;
    5. private String username;
    6. private String password;
    7. @Override
    8. public String toString() {
    9. return "User{" +
    10. "id=" + id +
    11. ", username='" + username + '\'' +
    12. ", password='" + password + '\'' +
    13. '}';
    14. }
    15. public int getId() {
    16. return id;
    17. }
    18. public void setId(int id) {
    19. this.id = id;
    20. }
    21. public String getUsername() {
    22. return username;
    23. }
    24. public void setUsername(String username) {
    25. this.username = username;
    26. }
    27. public String getPassword() {
    28. return password;
    29. }
    30. public void setPassword(String password) {
    31. this.password = password;
    32. }
    33. public User(int id, String username, String password) {
    34. this.id = id;
    35. this.username = username;
    36. this.password = password;
    37. }
    38. public User() {
    39. }
    40. }

    4. 创建映射接口

    创建com.sh.mapper.UserMapper

    1. package com.sh.mapper;
    2. import com.sh.pojo.User;
    3. import java.util.List;
    4. public interface UserMapper {
    5. List selectAll();
    6. }

    5. 创建测试类

    1. package com.sh;
    2. import static org.junit.Assert.assertTrue;
    3. import com.sh.mapper.UserMapper;
    4. import com.sh.pojo.User;
    5. import org.junit.Test;
    6. import org.springframework.context.support.ClassPathXmlApplicationContext;
    7. import org.w3c.dom.ls.LSException;
    8. import java.util.List;
    9. /**
    10. * Unit test for simple App.
    11. */
    12. public class AppTest
    13. {
    14. /**
    15. * Rigorous Test :-)
    16. */
    17. @Test
    18. public void shouldAnswerWithTrue()
    19. {
    20. assertTrue( true );
    21. }
    22. @Test
    23. public void test(){
    24. ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
    25. //底层已经封装好了获取代理对象的方法,直接通过接口的类对象就能获取代理对象
    26. UserMapper mapper = ac.getBean(UserMapper.class);
    27. List list = mapper.selectAll();
    28. System.out.println(list);
    29. }
    30. }

    十二、Spring整合web

    Spring 项目不需要依赖Web环境,但是Java项目大多数是Web项目,所以Spring也支持集成到Web环境中。

    Spring 集成Web环境是通过Listener实现的,在ServletContext对象创建时加载Spring容器。Spring已经在spring-web.jar包中提供了ContextLoaderListener实现加载Spring配置文件的代码。我们只需要在web.xml配置标签让ContextLoaderListener生效,并且告诉ContextLoaderListener加载Spring配置文件的路径即可。

    1. 创建项目,并添加依赖

    创建Maven的web项目(添加上webapp目录等,并配置web模块),并在pom.xml配置依赖。

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    3. <modelVersion>4.0.0modelVersion>
    4. <packaging>warpackaging>
    5. <name>Spring03Webname>
    6. <groupId>com.shgroupId>
    7. <artifactId>Spring03WebartifactId>
    8. <version>1.0-SNAPSHOTversion>
    9. <dependencies>
    10. <dependency>
    11. <groupId>junitgroupId>
    12. <artifactId>junitartifactId>
    13. <version>4.11version>
    14. <scope>testscope>
    15. dependency>
    16. <dependency>
    17. <groupId>org.springframeworkgroupId>
    18. <artifactId>spring-contextartifactId>
    19. <version>5.3.16version>
    20. dependency>
    21. <dependency>
    22. <groupId>org.springframeworkgroupId>
    23. <artifactId>spring-webartifactId>
    24. <version>5.3.16version>
    25. dependency>
    26. <dependency>
    27. <groupId>javax.servletgroupId>
    28. <artifactId>javax.servlet-apiartifactId>
    29. <version>4.0.1version>
    30. <scope>providedscope>
    31. dependency>
    32. <dependency>
    33. <groupId>javax.servlet.jspgroupId>
    34. <artifactId>javax.servlet.jsp-apiartifactId>
    35. <version>2.3.3version>
    36. <scope>providedscope>
    37. dependency>
    38. dependencies>
    39. <build>
    40. <plugins>
    41. <plugin>
    42. <groupId>org.apache.tomcat.mavengroupId>
    43. <artifactId>tomcat7-maven-pluginartifactId>
    44. <version>2.2version>
    45. <configuration>
    46. <path>/path>
    47. <port>80port>
    48. <uriEncoding>UTF-8uriEncoding>
    49. configuration>
    50. plugin>
    51. plugins>
    52. build>
    53. project>

    2. 编写类

    随意创建一个类,为了测试是否能从容器中获取到bean。

    创建com.sh.pojo.User。

    1. package com.sh.pojo;
    2. import java.io.Serializable;
    3. public class User implements Serializable {
    4. private int id;
    5. private String username;
    6. private String password;
    7. @Override
    8. public String toString() {
    9. return "User{" +
    10. "id=" + id +
    11. ", username='" + username + '\'' +
    12. ", password='" + password + '\'' +
    13. '}';
    14. }
    15. public int getId() {
    16. return id;
    17. }
    18. public void setId(int id) {
    19. this.id = id;
    20. }
    21. public String getUsername() {
    22. return username;
    23. }
    24. public void setUsername(String username) {
    25. this.username = username;
    26. }
    27. public String getPassword() {
    28. return password;
    29. }
    30. public void setPassword(String password) {
    31. this.password = password;
    32. }
    33. public User(int id, String username, String password) {
    34. this.id = id;
    35. this.username = username;
    36. this.password = password;
    37. }
    38. public User() {
    39. }
    40. }

    3. 编写配置文件

    建议:建立上applicationContext.xml的模板。

    里面创建User的bean即可。

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    5. <bean id="user" class="com.sh.pojo.User">
    6. <property name="username" value="zs"/>
    7. bean>
    8. beans>

    4. 配置监听器

    为了使spring容器只创建一次,避免每次访问都重新创建容器,可以使用静态代码创建容器,

    tomcat中有三个域对象:

    请求域,会话域,应用域

    应用域(ServletContext)在tomcat启动后创建,tomcat关闭后销毁,且服务器中都共用,且创建一次

    我们可以把spring容器存储在ServletContext中进行使用,可以通过监听器监听它的状态

    可以自己写一个监听器,监听ServletContext的状态

    1. package com.sh.lister;
    2. import org.springframework.context.ApplicationContext;
    3. import org.springframework.context.support.ClassPathXmlApplicationContext;
    4. import javax.servlet.ServletContext;
    5. import javax.servlet.ServletContextEvent;
    6. import javax.servlet.ServletContextListener;
    7. //配置监听器
    8. //让web项目启动时自动创建Spring容器对象
    9. //手写监听器
    10. public class AppListener implements ServletContextListener {
    11. @Override
    12. public void contextInitialized(ServletContextEvent sce) {
    13. //ServletContext初始化后就创建spring容器并保存在servletContext中
    14. ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    15. ServletContext servletContext = sce.getServletContext();
    16. servletContext.setAttribute("ac",ac);
    17. }
    18. @Override
    19. public void contextDestroyed(ServletContextEvent sce) {
    20. }
    21. }

    在web.xml中配置监听器,让web项目启动时自动创建Spring容器对象(WebApplicationContext)。

    1. DOCTYPE web-app PUBLIC
    2. "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    3. "http://java.sun.com/dtd/web-app_2_3.dtd" >
    4. <web-app>
    5. <display-name>Archetype Created Web Applicationdisplay-name>
    6. <listener>
    7. <listener-class>com.sh.lister.AppListenerlistener-class>
    8. listener>
    9. web-app>

    spring中内置了一个监听器,我们可以直接使用,但是需要对其进行配置

    上下文参数名param-name的值是固定的contextConfigLocation。这个值是监听器需要获取的值。

    上下文参数值需要带有classpath,表示加载类路径内容。target/classes目录内容。

    classpath*:表示当前项目依赖的jar中资源也会寻找。

    classpath:后面的值支持星号。例如applicationContext-*.xml表示加载所有以applicationContext-开头的xml文件。

    1. DOCTYPE web-app PUBLIC
    2. "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    3. "http://java.sun.com/dtd/web-app_2_3.dtd" >
    4. <web-app>
    5. <display-name>Archetype Created Web Applicationdisplay-name>
    6. <context-param>
    7. <param-name>contextConfigLocationparam-name>
    8. <param-value>classpath:applicationContext.xmlparam-value>
    9. context-param>
    10. <listener>
    11. <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
    12. listener>
    13. web-app>

    5. 编写Servlet

    1. package com.sh.controller;
    2. import com.sh.pojo.User;
    3. import org.springframework.context.ApplicationContext;
    4. import javax.servlet.ServletContext;
    5. import javax.servlet.ServletException;
    6. import javax.servlet.annotation.WebServlet;
    7. import javax.servlet.http.HttpServlet;
    8. import javax.servlet.http.HttpServletRequest;
    9. import javax.servlet.http.HttpServletResponse;
    10. import java.io.IOException;
    11. @WebServlet("/query")
    12. public class UserServlet extends HttpServlet {
    13. @Override
    14. protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    15. ServletContext servletContext = req.getServletContext();
    16. ApplicationContext ac = (ApplicationContext) servletContext.getAttribute("ac");
    17. User user = ac.getBean(User.class);
    18. System.out.println(user);
    19. }
    20. }

    6. 访问测试

  • 相关阅读:
    SpringMVC之定义注解强势来袭!!!
    Swoole v6 能否让 PHP 再次伟大?
    计算机视觉与模式识别实验1-4 图像的傅立叶变换
    centos docker下安装Minio服务
    spring注入的几种方式(文件配置以及注解方式)
    cameralink base 接口双通道任意图像数据源模拟
    聚类算法概要及相关知识准备
    大数据面试题之SQL题
    SpringMVC - 以 Servlet 3.0 的方式搭建 SSM 框架
    sp-踩坑小记
  • 原文地址:https://blog.csdn.net/m0_59163770/article/details/133866998