# Spring 框架详细学习

Spring 框架详细学习


学习Spring 框架目录

  • Spring概述

  • Spring框架结构

  • Spring Hello World例子

  • Spring Ioc 容器

  • Spring 依赖注入

    • Spring 基于构造函数的依赖注入
    • Spring 基于set方法的依赖注入
    • Spring 注入内部 Beans
    • Spring 注入集合
  • Spring Beans 自动装配

    • Spring 自动装配 byName
    • Spring 自动装配 byType
    • Spring 由构造函数自动装配
  • Spring 基于注解的配置

    • Spring @Required 注释
    • Spring @Autowired 注释
    • Spring @Qualifier 注释
  • Spring 框架的AOP

    • Spriing 中基于AOP的XML架构
    • Spring 中基于AOP的 @Aspect架构
  • Spring JDBC 框架

    • Spring JDBC 示例
    • Spring 中SQL的存储过程
  • Spring 事务管理

    • Spring 编程式事务管理
    • Spring 声明式事务管理
  • Spring Web MVC 框架

    • Spring MVC Hello World 例子
    • Spring MVC 表单处理例子
    • Spring 页面重定向例子
    • Spring 静态页面例子
    • Spring 异常处理例子
    • Spring 使用 Log4J 记录日志

Spring概述

在这里插入图片描述

Spring 是一个轻量级开源框架,它以IOC(控制反转)和AOP(面向切面编程)为内核,使用基本的JavaBean来完成工作。


Spring框架结构

体系结构

在这里插入图片描述

核心模块
  • Core Container(核心容器)
    • Beans:核心组件是BeanFactory,对Bean进行管理。是工厂模式的实现。
    • Core:Spring框架的基本组成部分。
    • Context:访问定义和任何对象的媒介。ApplicationContext接口是上下文模块的焦点。
    • SpEL:是运行时查询和操作对象图的强大的表达式语言。
  • Web 模块
    • Web:提供面向Web的基本功能。例如使用Servlert监听器初始化Ioc容器等。
    • Servlert:Spring模型——视图——控制层(MVC)实现Web应用程序。
    • Struts:集成Struts Web层。
    • Protlet:类似Web-Servlert的功能。
  • Data Access / Integration(数据访问/集成)
    • JDBC:提供JDBC抽象层。
    • ORM:提供对象关系映射API,例如Hibernate、JPA等的集成。
    • OXM:提供支持对象/XML映射的抽象层实现。
    • JMS:Java消息服务。
    • Transactions:支持编程和声明式事务实现特殊接口类。编程式事务需要自己写 beginTransaction()、commit()、rollback() 等事务管理方法,声明式事务是通过注解或配置由 spring 自动处理,编程式事务粒度更细。
  • 其他模块
    • AOP:提供面向切面编程的实现。
    • Aspects:功能强大且成熟的面向切面编程的实现。
    • Messaging
    • Instrumentation

Spring Hello World例子

- Idea新建Maven项目,添加Spring依赖
<!-- spring依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.2.RELEASE</version>
</dependency>
  • Idea中项目结构图如下:

在这里插入图片描述

  • web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
    <display-name>springMVC</display-name>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
</web-app>

添加Tomcat启动就Ok了。


Spring Ioc 容器

Spring 容器是Spring 框架的核心,Ioc容器具有依赖注入功能的容器,可以创建对象,Ioc容器负责实例化等操作。Spring提供了两种不同类型的容器。
容器名称 容器描述
Spring BeanFactory容器 给DI提供和基本的支持。
Spring ApplicationContext 容器 加载配置文件中定义的bean,另外增加了其他功能。
Spring BeanFactory 容器
  • 主要功能是为依赖注入提供支持。在Spring中,有大量对BeanFactory接口的实现。其中最常用的是XmlBeanFactory类,从Xml中读取配置数据。

使用XmlBeanFactory实例如下:

  • HelloWorld.java
public class HelloWorld {
    
    

    private int id;
    private String message;

    @Override
    public String toString() {
    
    
        return "HelloWorld{" +
                "id=" + id +
                ", message='" + message + '\'' +
                '}';
    }
    // 省略setget方法
}
  • HelloWorld.xml
<?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-3.0.xsd">

    <bean id="helloWorld" class="com.li.entity.HelloWorld">
        <property name="message" value="张三"></property>
        <property name="id" value="1"></property>
    </bean>
</beans>
  • 测试方法
@Test
public void test1(){
    
    
    // 定义Bean的文件地址
    ClassPathResource resource=new ClassPathResource("HelloWorld.xml");
    DefaultListableBeanFactory factory=new DefaultListableBeanFactory();
    XmlBeanDefinitionReader reader=new XmlBeanDefinitionReader(factory);
    reader.loadBeanDefinitions(resource);

    HelloWorld helloWorld = factory.getBean(HelloWorld.class);
    System.out.println(helloWorld.toString());
}

Spring ApplicationContext 容器

ApplicationContext 是BeanFactory的子接口,也被称为应用上下文,它有两个常用的实现类。

  • ClassPathXmlApplicationContext
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
    
    
    this(new String[] {
    
    configLocation}, true, null);
}
  • FileSystemXmlApplicationContext
public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
    
    
    this(new String[] {
    
    configLocation}, true, null);
}
  • WebXmlApplicationContext:该容器会在一个 web 应用程序的范围内加载在 XML 文件中已被定义的 bean。

两种容器使用的区别:如果Bean的一个属性没有注入,使用BeanFactory加载后,在第一次调用getBean()方法会抛出异常, ApplicationContext 则在初始化时自检,这样有利于检查所依赖的属性是否注入。


Spring Bean 定义

Bean是一个被实例化、组装通过SpringIoc容器所管理的对象。

  • Bean所包含的属性
属性 意义
class 指定用来创建Bean的类
name 指定唯一的Bean标识,可以使用Id或name进行唯一标识
scope 指定Bean的作用域
constructor-arg 用来注入依赖关系
properties 用来注入依赖关系
autowiring mode 用来注入依赖关系
lazy-initialization mode 延迟初始化的 bean 告诉 IoC 容器在它第一次被请求时,而不是在启动时去创建一个 bean 实例。
  • Spring 配置元数据:有下面三种方法把配置元数据提供给Spring容器。

    • 基于Xml的配置文件
    • 基于注解的配置:@Component取代<bean class="">、@Component(“id”)取代<bean id=" " class=" ">。注解使用的前提,在xml中配置让spring扫描含有的注解类。
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 组件扫描,扫描含有注解的类 -->
    <context:component-scan base-package="com.cc.study.annotation"></context:component-scan>

</beans>
  • 基于Java的配置

Spring Bean 作用域

当在Spring中定义一个Bean时候,必须声明Bean作用域的选项。

作用域 描述
singleton SpingIoc容器中仅存在一个Bean实例,以单例方式存在
prototype 每次从容器中调用Bean时都返回一个新的实例
request 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
session 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean,仅适用于WebApplicationContext环境
global-session 暂不了解
  • singleton配置方式
<bean id="helloWorld" class="com.li.entity.HelloWorld" scope="singleton">
    <property name="message" value="张三"  ></property>
    <property name="id" value="1"></property>
</bean>

Spring Bean 生命周期

Bean的生命周期:Bean的定义——Bean的初始化——Bean的使用——Bean的销毁

  • HelloWorld.java
public void init(){
    
    
    System.out.println("HelloWorld Bean创建了");
}

public void destroy(){
    
    
    System.out.println("HelloWorld Bean销毁了");
}
  • HelloWorld.xml
<bean id="helloWorld" class="com.li.entity.HelloWorld" scope="singleton" init-method="init" destroy-method="destroy">
    <property name="message" value="张三"  ></property>
    <property name="id" value="1"></property>
</bean>
  • Test.java
@Test
public void test3(){
    
    
    AbstractApplicationContext context=new ClassPathXmlApplicationContext("HelloWorld.xml");
    HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");
    System.out.println(helloWorld);
    context.registerShutdownHook();
}

Spring 依赖注入

Spring框架的核心功能之一就是通过依赖注入的方式来管理Bean之间的依赖关系。每个基于应用程序的 java 都有几个对象,由这些对象一起工作来呈现出终端用户所看到的工作的应用程序。spring通过注入对象的方式进行管理这些Bean之间的依赖关系。能注入的数据类型有基本类型和String、其他Bean类型

Spring 基于构造函数的依赖注入
  • type:用于不指定要注入数据的数据类型
  • index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值。
  • name:用于指定给构造函数中指定名称的参数赋值。
  • ref:指定其他的Bean类型。

两个实体类

  • People.java
public class People {
    
    

    private int id;
    private Message message;

    public People(int id, Message message) {
    
    
        System.out.println("我是People的构造函数!"+"===="+id+"======"+message);
        this.id = id;
        this.message = message;
    }
}
  • Message.java
public class Message {
    
    

    private int id;
    private String world;

    public Message(int id, String world) {
    
    
        System.out.println("我是Message的构造函数"+"===="+id+"====="+world);
        this.id = id;
        this.world = world;
    }
}
  • peopleBean.xml:通过构造函数的方式注入,配置实例如下:
<bean id="people" class="com.li.entity.People">
    <constructor-arg type="int" name="id"><value >10</value></constructor-arg>
    <constructor-arg ref="message"></constructor-arg>
</bean>

<bean id="message" class="com.li.entity.Message">
    <constructor-arg type="int" name="id"><value>12</value></constructor-arg>
    <constructor-arg type="java.lang.String" name="world"><value>"张三"</value></constructor-arg>
</bean>
Spring 基于set方法注入
  • name:用于指定注入时所调用的set方法名称
  • value:用于提供基本类型和String类型的数据
  • ref:用于指定其他的bean类型(在spring的ioc核心容器中出现过的bean对象)数据
<bean id="accountServiceSet" class="com.dudu.service.impl.AccountServiceImplSet">
    <property name="name" value="骆闻舟"></property>
    <property name="age" value="21"></property>
    <property name="birthday" ref="now"></property>
</bean>
Spring 注入内部 Beans
  • people.java
public class People {
    
    

    private int id;
    private Message message;

    public People(int id, Message message) {
    
    
        System.out.println("我是People的构造函数!"+"===="+id+"======"+message);
        this.id = id;
        this.message = message;
    }

    public Message message(){
    
    
        return message;
    }

    public void showMessage(){
    
    
        message.show();
    }
}

  • Bean.xml
<bean id="people" class="...">
    <property name="message">
        <bean id="message" class="..."/>
    </property>
</bean>
Spring 注入集合
  • testBean.xml
<bean id="accountServiceList" class="com.dudu.service.impl.AccountServiceImplList">
    <property name="myList">
        <list><!-- 标签可以换成array或set -->
            <value>骆闻舟</value>
            <value>长庚</value>
            <value>赵锦辛</value>
            <!-- <ref bean="now"><bean></bean></ref> -->
        </list>
    </property>
    <property name="myMap">
        <map><!-- 标签可以换成props -->
            <entry key="骆闻舟" value="费渡"/><!-- 标签可以换成prop -->
            <entry key="长庚" value="顾昀"/><!-- <prop key="骆闻舟">费渡</prop> -->
            <entry key="黎朔" value="赵锦辛"/>
        </map>
    </property>
    <!-- 配置独立的list -->
    <util:list id="cars">
        <ref bean=""></ref>
    </util:list>
</bean>

Spring Beans 自动装配

自动装配模式

方法 描述
byName 由属性名自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byName。然后尝试匹配,并且将它的属性与在配置文件中被定义为相同名称的 beans 的属性进行连接。
byType 由属性数据类型自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byType。然后如果它的类型匹配配置文件中的一个确切的 bean 名称,它将尝试匹配和连接属性的类型。如果存在不止一个这样的 bean,则一个致命的异常将会被抛出。
constructor 类似于 byType,但该类型适用于构造函数参数类型。如果在容器中没有一个构造函数参数类型的 bean,则一个致命错误将会发生。
Spring 自动装配 byName
<bean id="people" class="com.li.People" autowire="byName">
    <property name="name" value="张三" />
</bean>
Spring 自动装配 byType
<bean id="people" class="com.li.People" autowire="byType">
    <property name="name" value="张三" />
</bean>
Spring 由构造函数自动装配

一个确切的 bean 名称,它将尝试匹配和连接属性的类型。如果存在不止一个这样的 bean,则一个致命的异常将会被抛出。 |
|constructor | 类似于 byType,但该类型适用于构造函数参数类型。如果在容器中没有一个构造函数参数类型的 bean,则一个致命错误将会发生。 |

Spring 自动装配 byName
<bean id="people" class="com.li.People" autowire="byName">
    <property name="name" value="张三" />
</bean>
Spring 自动装配 byType
<bean id="people" class="com.li.People" autowire="byType">
    <property name="name" value="张三" />
</bean>
Spring 由构造函数自动装配

Spring 基于注解的配置

从Spring2.5开始可以使用注解来配置依赖注入,而不是采用xml描述一个bean,可以通过注解进行配置Bean。如果想用注解进行配置,可以加上配置。

<!-- 使用注解进行配置 -->
<context:annotation-config/>
注解 注解 & 描述
@Required @Required 注解应用于 bean 属性的 setter 方法。
@Autowired @Autowired 注解可以应用到 bean 属性的 setter 方法,非 setter 方法,构造函数和属性。
@Qualifier 通过指定确切的将被连线的 bean,@Autowired 和 @Qualifier 注解可以用来删除混乱。
Spring @Required 注释

@Required 注释应用于 bean 属性的 setter 方法,它表明受影响的 bean 属性在配置时必须放在 XML 配置文件中,否则容器就会抛出一个 BeanInitializationException 异常。

Spring @Autowired 注释

使用 spring 开发时,进行配置主要有两种方式,一是 xml 的方式,二是 java config 的方式。@Autowired 注释的功能就是为我们注入一个定义好的 bean。

Spring @Qualifier 注释

当你创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配,在这种情况下,你可以使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱。


Spring 框架的AOP

Aop将影响多个模块的行为方法进行封装到一个可重用模块,并将其命名为切面(Aspect),与业务无关,便于减少系统的重复代码,降低模块之间的耦合度,利于后面的可操作性和可维护性。

  • AOP核心概念
概念 意义
切入点(Pointcut) 在哪些类,哪些方法上切入
通知(Advice) 在方法执行的时候(方法前,方法后,方法前后)做什么
切面(Aspect) 在什么时机,什么什么地方,作什么增强
织入(Weaving) 把切面加入到对象,并创建出代理对象的过程
Spriing 中基于AOP的XML架构
  • Aspect依赖
<!-- Aspect -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.2</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.2</version>
</dependency>
<dependency>
    <groupId>aopalliance</groupId>
    <artifactId>aopalliance</artifactId>
    <version>1.0</version>
</dependency>
  • message.java:要进行切入的对象
public class Message {
    
    

    private int id;
    private String message;


    public void showMessage(){
    
    
        System.out.println(this.id+"========"+this.message);
        System.out.println("我是Message的show()");
    }
    // 省略setget()
}
  • 连接点
public interface Logging {
    
    
    public void beforeAdvice();
    public void afterAdvice();
    public void afterReturningAdvice(Object retVal);
}
public class LoggingImpl implements  Logging {
    
    
    @Override
    public void beforeAdvice() {
    
    
        System.out.println("方法之前");
    }
    @Override
    public void afterAdvice()  {
    
    
        System.out.println("方法之后");
    }
    @Override
    public void afterReturningAdvice(Object retVal){
    
    
        System.out.println("方法返回之后得到的返回值为=======" + retVal.toString());
    }
}
  • bean的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">


    <bean id="message" class="com.li.entity.Message">
        <property name="id" value="1"></property>
        <property name="message" value="testmessage"></property>
    </bean>

    <bean id="loggingImpl" class="com.li.entity.LoggingImpl"></bean>

    <aop:config >
        <aop:aspect id="testlog" ref="loggingImpl">
            <aop:pointcut id="selectAll" expression="execution(* com.li.entity.*.*(..))"/>
            <aop:before method="beforeAdvice" pointcut-ref="selectAll" ></aop:before>
            <aop:after method="afterAdvice"  pointcut-ref="selectAll"></aop:after>
            <aop:after-returning  returning="retVal" method="afterReturningAdvice" pointcut-ref="selectAll"></aop:after-returning>

        </aop:aspect>
    </aop:config>

</beans>
Spring 中基于AOP的 @Aspect架构
  • 需要的依赖同上面。

  • 连接点

@Aspect
public class LogAspect {
    
    

    @Pointcut("execution(* com.li.entity.*.*(..))")
    private void selectAll(){
    
    
        System.out.println("定义的连接点");
    }

    @Before("selectAll()")
    public void beforeAdvice(){
    
    
        System.out.println("=========方法前");
    }

    @After("selectAll()")
    public void afterAdvice(){
    
    
        System.out.println("=========方法后");
    }
    
}
  • bean的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    <bean id="message" class="com.li.entity.Message">
        <property name="id" value="1"></property>
        <property name="message" value="testmessage"></property>
    </bean>
    <bean id="logAspect" class="com.li.aspect.LogAspect"></bean>

</beans>

Spring JDBC 框架

在使用普通的jdb操作数据库时候,需要些代码处理异常。Spring jdbc框架负责所有的底层细节,从开始打开连接、准备和执行Sql语句、事务处理、异常处理等。

  • JdbcTemplate 类

使用JdbcTemplate常用的方法是在Spring配置文件中配置数据源,共享数据源Bean进行注入,实例化JdbcTemplate。

public JdbcTemplate(DataSource dataSource) {
    
    
    setDataSource(dataSource);
    afterPropertiesSet();
}
Spring JDBC 示例
  • 添加Maven依赖
<!-- Spring jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.1.8.RELEASE</version>
</dependency>

<!-- Mysql Connector -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.39</version>
</dependency>
  • beam.xml
    <!-- 配置数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    <property name="url" value=""></property>
    <property name="username" value=""></property>
    <property name="password" value=""></property>
</bean>

  • 使用
@Test
public void test6(){
    
    
    ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
    DataSource dataSource = context.getBean("dataSource", DataSource.class);
    JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
    List<Map<String, Object>> maps = jdbcTemplate.queryForList("select * test");
    maps.forEach(x->{
    
    
        System.out.println(x);
    });
}

。。。。。。未完待续!

猜你喜欢

转载自blog.csdn.net/qq_37248504/article/details/109135995