4.SpringIOC应用

1 Spring IoC基础

1.1 BeanFactoryApplicationContext区别

BeanFactory Spring 框架中 IoC 容器的顶层接⼝ , 它只是⽤来定义⼀些基础功能 , 定义⼀些基础规范 ,
ApplicationContext 是它的⼀个⼦接⼝,所以 ApplicationContext 是具备 BeanFactory 提供的全部功能
的。
通常,我们称 BeanFactory SpringIOC 的基础容器, ApplicationContext 是容器的⾼级接⼝,⽐
BeanFactory 要拥有更多的功能,⽐如说国际化⽀持和资源访问( xml java 配置类)等等
 

 

启动 IoC 容器的⽅式
   1.Java 环境下启动 IoC 容器
            ClassPathXmlApplicationContext :从类的根路径下加载配置⽂件(推荐使⽤)
            FileSystemXmlApplicationContext :从磁盘路径上加载配置⽂件
              AnnotationConfifigApplicationContext :纯注解模式下启动 Spring 容器
  2. Web 环境下启动 IoC 容器
             从 xml 启动容器
 
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>


  <!--配置Spring ioc容器的配置文件-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  <!--使用监听器启动Spring的IOC容器-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
</web-app>

    从配置类启动容器

<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name> Archetype Created Web Application </display-name>
<!-- 告诉 ContextloaderListener 知道我们使⽤注解的⽅式启动 ioc 容器 -->
<context-param>
<param-name> contextClass </param-name>
<param
value> org.springframework.web.context.support.AnnotationConfigWebAppli
cationContext </param-value>
</context-param>
<!-- 配置启动类的全限定类名 -->
<context-param>
<param-name> contextConfigLocation </param-name>
<param-value> com.lagou.edu.SpringConfig </param-value>
</context-param>
<!-- 使⽤监听器启动 Spring IOC 容器 -->
<listener>
<listener
class> org.springframework.web.context.ContextLoaderListener </listener
class>
</listener>
 

1.2 xml模式

本部分内容我们不采⽤⼀⼀讲解知识点的⽅式,⽽是采⽤ Spring IoC xml 模式改造我们前⾯⼿写的
IoC AOP 实现,在改造的过程中,把各个知识点串起来。
xml ⽂件头
 
1.引入spring相关依赖
 
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.3.5</version>
</dependency>

把原来的bean.xml修改成为spring配置文件,修改名字为applicationContext.xml,加入spring的文件头

<?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
 https://www.springframework.org/schema/beans/spring-beans.xsd">
实例化 Bean 的三种⽅式
⽅式⼀:使⽤⽆参构造函数
在默认情况下,它会通过反射调⽤⽆参构造函数来创建对象。如果类中没有⽆参构造函数,将创建
失败。(这是推荐使用的方式
 
<!--方式一:使用无参构造器(推荐)-->
<bean id="connectionUtils" class="com.lagou.edu.utils.ConnectionUtils"></bean>
⽅式⼆:使⽤静态⽅法创建
在实际开发中,我们使⽤的对象有些时候并不是直接通过构造函数就可以创建出来的,它可能在创
建的过程 中会做很多额外的操作。此时会提供⼀个创建对象的⽅法,恰好这个⽅法是 static 修饰的
⽅法,即是此种情 况。
例如,我们在做 Jdbc 操作时,会⽤到 java.sql.Connection 接⼝的实现类,如果是 mysql 数据库,那
么⽤的就 是 JDBC4Connection ,但是我们不会去写 JDBC4Connection connection = new
JDBC4Connection() ,因 为我们要注册驱动,还要提供 URL 和凭证信息,
DriverManager.getConnection ⽅法来获取连接。

那么在实际开发中,尤其早期的项⽬没有使⽤Spring框架来管理对象的创建,但是在设计时使⽤了

⼯⼚模式 解耦,那么当接⼊ spring 之后,⼯⼚类创建对象就具有和上述例⼦相同特征,即可采⽤
此种⽅式配置
 
<!--方式二:静态方法-->
<!--<bean id="connectionUtils" class="com.lagou.edu.factory.CreateBeanFactory" factory-method="getInstanceStatic"/>-->
⽅式三:使⽤实例化⽅法创建
此种⽅式和上⾯静态⽅法创建其实类似,区别是⽤于获取对象的⽅法不再是 static 修饰的了,⽽是
类中的⼀ 个普通⽅法。此种⽅式⽐静态⽅法创建的使⽤⼏率要⾼⼀些。
在早期开发的项⽬中,⼯⼚类中的⽅法有可能是静态的,也有可能是⾮静态⽅法,当是⾮静态⽅法
时,即可 采⽤下⾯的配置
 
<!--方式三:实例化方法-->
<!--<bean id="createBeanFactory" class="com.lagou.edu.factory.CreateBeanFactory"></bean>
<bean id="connectionUtils" factory-bean="createBeanFactory" factory-method="getInstance"/>-->

创建CreateBeanFactory,进行测试

package com.lagou.edu.factory;

import com.lagou.edu.utils.ConnectionUtils;

public class CreateBeanFactory {

    public static ConnectionUtils getInstanceStatic() {
        return new ConnectionUtils();
    }

    public ConnectionUtils getInstance() {
        return new ConnectionUtils();
    }
}

测试方法

ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");

System.out.println("accountDao:" + accountDao);
AccountDao accountDao1 = (AccountDao) applicationContext.getBean("accountDao");
System.out.println("accountDao1:" + accountDao1);
Object connectionUtils = applicationContext.getBean("connectionUtils");
System.out.println(connectionUtils);

结果

scope:定义bean的作用范围

            singleton:单例,IOC容器中只有一个该类对象,默认为singleton
            prototype:原型(多例),每次使用该类的对象(getBean),都返回给你一个新的对象,Spring只创建对象,不管理对象
Bean X 及⽣命周期
作⽤范围的改变
spring 框架管理 Bean 对象的创建时, Bean 对象默认都是单例的,但是它⽀持配置的⽅式改
变作⽤范围。作⽤范围官⽅提供的说明如下图

 

在上图中提供的这些选项中,我们实际开发中⽤到最多的作⽤范围就是 singleton (单例模式)和
prototype (原型模式,也叫多例模式)。配置⽅式参考下⾯的代码
 

 <bean id="connectionUtils" class="com.lagou.edu.utils.ConnectionUtils" scope="prototype"></bean>

不同作⽤范围的⽣命周期
单例模式: singleton
对象出⽣:当创建容器时,对象就被创建了。
对象活着:只要容器在,对象⼀直活着。
对象死亡:当销毁容器时,对象就被销毁了。
⼀句话总结:单例模式的 bean 对象⽣命周期与容器相同。
多例模式: prototype
对象出⽣:当使⽤对象时,创建新的对象实例。
对象活着:只要对象在使⽤中,就⼀直活着。
对象死亡:当对象⻓时间不⽤时,被 java 的垃圾回收器回收了。
⼀句话总结:多例模式的 bean 对象, spring 框架只负责创建,不负责销毁。
Bean 标签属性
在基于 xml IoC 配置中, bean 标签是最基础的标签。它表示了 IoC 容器中的⼀个对象。换句话
说,如果⼀个对象想让 spring 管理,在 XML 的配置中都需要使⽤此标签配置, Bean 标签的属性如
下:
id 属性: ⽤于给 bean 提供⼀个唯⼀标识。在⼀个标签内部,标识必须唯⼀。
class 属性: ⽤于指定创建 Bean 对象的全限定类名。
name 属性: ⽤于给 bean 提供⼀个或多个名称。多个名称⽤空格分隔。
factory-bean 属性: ⽤于指定创建当前 bean 对象的⼯⼚ bean 的唯⼀标识。当指定了此属性之后,
class 属性失效。
factory-method 属性: ⽤于指定创建当前 bean 对象的⼯⼚⽅法,如配合 factory-bean 属性使⽤,
class 属性失效。如配合 class 属性使⽤,则⽅法必须是 static 的。
scope 属性: ⽤于指定 bean 对象的作⽤范围。通常情况下就是 singleton 。当要⽤到多例模式时,
可以配置为 prototype
init-method 属性: ⽤于指定 bean 对象的初始化⽅法,此⽅法会在 bean 对象装配后调⽤。必须是
⼀个⽆参⽅法。
destory-method 属性: ⽤于指定 bean 对象的销毁⽅法,此⽅法会在 bean 对象销毁前执⾏。它只
能为 scope singleton 时起作⽤。
 
JdbcAccountDaoImpl加入测试方法
 
public void init() {
    System.out.println("初始化方法.....");
}

public void destory(){
    System.out.println("销毁方法.....");
}

在applicationContext.xml中调用

<bean id="accountDao" class="com.lagou.edu.dao.impl.JdbcTemplateDaoImpl" scope="singleton" init-method="init" destroy-method="destory">
测试
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
applicationContext.getBean("accountDao"); System.out.println("accountDao:" + accountDao); AccountDao accountDao1 = (AccountDao) applicationContext.getBean("accountDao"); System.out.println("accountDao1:" + accountDao1); Object connectionUtils = applicationContext.getBean("connectionUtils"); System.out.println(connectionUtils);
applicationContext.close();
结果
 
DI 依赖注⼊的xml配置
依赖注⼊分类
按照注⼊的⽅式分类
构造函数注⼊: 顾名思义,就是利⽤带参构造函数实现对类成员的数据赋值。
set ⽅法注⼊: 它是通过类成员的 set ⽅法实现数据的注⼊。(使⽤最多的)
按照注⼊的数据类型分类
基本类型和 String
注⼊的数据类型是基本类型或者是字符串类型的数据。
其他 Bean 类型 注⼊的数据类型是对象类型,称为其他 Bean 的原因是,这个对象是要求出现在 IoC 容器
中的。那么针对当前 Bean 来说,就是其他 Bean 了。
复杂类型(集合类型)
注⼊的数据类型是 Aarry List Set Map Properties 中的⼀种类型。
依赖注⼊的配置实现之构造函数注⼊ 顾名思义,就是利⽤构造函数实现对类成员的赋值。它
的使⽤要求是,类中提供的构造函数参数个数必须和配置的参数个数⼀致,且数据类型匹
配。同时需要注意的是,当没有⽆参构造时,则必须提供构造函数参数的注⼊,否则Spring 框架会报错。
 
set注入例子
 
JdbcAccountDaoImpl加入属性和set方法和构造函数
private ConnectionUtils connectionUtils;
private String name;
private int sex;
private float money;

public void setConnectionUtils(ConnectionUtils connectionUtils) {
    this.connectionUtils = connectionUtils;
}

public void setName(String name) {
    this.name = name;
}

public void setSex(int sex) {
    this.sex = sex;
}

public void setMoney(float money) {
    this.money = money;
}


xml配置文件
 
<bean id="accountDao" class="com.lagou.edu.dao.impl.JdbcTemplateDaoImpl" scope="singleton" init-method="init" destroy-method="destory">
<property name="ConnectionUtils" ref="connectionUtils"/>
<property name="name" value="zhangsan"/>
<property name="sex" value="1"/>
<property name="money" value="100.3"/>
</bean>
在使⽤ set ⽅法注⼊时,需要使⽤ property 标签,该标签属性如下:
name :指定注⼊时调⽤的 set ⽅法名称。(注:不包含 set 这三个字⺟ ,druid 连接池指定属性名称)
value :指定注⼊的数据。它⽀持基本类型和 String 类型。
ref :指定注⼊的数据。它⽀持其他 bean 类型。写的是其他 bean 的唯⼀标识。
复杂数据类型注⼊ ⾸先,解释⼀下复杂类型数据,它指的是集合类型数据。集合分为两类,⼀类
List 结构(数组结构),⼀类是 Map 接⼝(键值对) 。
接下来就是注⼊的⽅式的选择,只能在构造函数和 set ⽅法中选择,我们的示例选⽤ set ⽅法注⼊。
 

debug 模式

构造器注入

在JdbcAccountDaoImpl加入构造器

public JdbcAccountDaoImpl(ConnectionUtils connectionUtils, String name, int sex, float money) {
    this.connectionUtils = connectionUtils;
    this.name = name;
    this.sex = sex;
    this.money = money;
}

xml配置文件

<bean id="accountDao" class="com.lagou.edu.dao.impl.JdbcTemplateDaoImpl" scope="singleton" init-method="init" destroy-method="destory">
<constructor-arg index="0" ref="connectionUtils"/>
<constructor-arg index="1" value="zhangsan"/>
<constructor-arg index="2" value="1"/>
<constructor-arg index="3" value="100.5"/>
</bean>

debug

 构造器index属性不太方便,因为要核对下标,可以使用name,<!--name:按照参数名称注入,index按照参数索引位置注入-->

<constructor-arg name="connectionUtils" ref="connectionUtils"/>
<constructor-arg name="name" value="zhangsan"/>
<constructor-arg name="sex" value="1"/>
<constructor-arg name="money" value="100.6"/>
在使⽤构造函数注⼊时,涉及的标签是 constructor-arg ,该标签有如下属性:
name :⽤于给构造函数中指定名称的参数赋值。
index :⽤于给构造函数中指定索引位置的参数赋值。
value :⽤于指定基本类型或者 String 类型的数据。
ref :⽤于指定其他 Bean 类型的数据。写的是其他 bean 的唯⼀标识。
依赖注⼊的配置实现之 set ⽅法注⼊
顾名思义,就是利⽤字段的 set ⽅法实现赋值的注⼊⽅式。此种⽅式在实际开发中是使⽤最多的注
⼊⽅式。
 

set设置

在JdbcAccountDaoImpl加入

private String[] myArray;
private Map<String,String> myMap;
private Set<String> mySet;
private Properties myProperties;

public void setMyArray(String[] myArray) {
    this.myArray = myArray;
}

public void setMyMap(Map<String, String> myMap) {
    this.myMap = myMap;
}

public void setMySet(Set<String> mySet) {
    this.mySet = mySet;
}

public void setMyProperties(Properties myProperties) {
    this.myProperties = myProperties;
}

 <bean id="accountDao" class="com.lagou.edu.dao.impl.JdbcTemplateDaoImpl" scope="singleton" init-method="init" destroy-method="destory">

<property name="myArray">
    <array>
        <value>array1</value>
        <value>array2</value>
        <value>array3</value>
    </array>
</property>

<property name="myMap">
    <map>
        <entry key="key1" value="value1"/>
        <entry key="key2" value="value2"/>
    </map>
</property>

<property name="mySet">
    <set>
        <value>set1</value>
        <value>set2</value>
    </set>
</property>

<property name="myProperties">
    <props>
        <prop key="prop1">value1</prop>
        <prop key="prop2">value2</prop>
    </props>
</property>
</bean>

 

 

List 结构的集合数据注⼊时, array , list , set 这三个标签通⽤,另外注值的 value 标签内部
可以直接写值,也可以使⽤ bean 标签配置⼀个对象,或者⽤ ref 标签引⽤⼀个已经配合的 bean
的唯⼀标识。
Map 结构的集合数据注⼊时, map 标签使⽤ entry ⼦标签实现数据注⼊, entry 标签可以使
key value 属性指定存⼊ map 中的数据。使⽤ value-ref 属性指定已经配置好的 bean 的引⽤。
同时 entry 标签中也可以使⽤ ref 标签,但是不能使⽤ bean 标签。⽽ property 标签中不能使
ref 或者 bean 标签引⽤对象
 

1.3 xml与注解相结合模式

注意:
1 )实际企业开发中,纯 xml 模式使⽤已经很少了
2 )引⼊注解功能,不需要引⼊额外的 jar
3 xml+ 注解结合模式, xml ⽂件依然存在,所以, spring IOC 容器的启动仍然从加载 xml 开始
4 )哪些 bean 的定义写在 xml 中,哪些 bean 的定义使⽤注解
 
第三⽅ jar 中的 bean 定义在 xml ,⽐如德鲁伊数据库连接池 ,在applicationContext.xml文件中进行配置
 
<!--第三方jar中的bean定义在xml中-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${jdbc.driver}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

在ConnectionUtils注入

private DataSource dataSource;

private void setDataSource(DataSource dataSource){
    this.dataSource=dataSource;
}

使用

 配置依赖

<bean id="connectionUtils" class="com.lagou.edu.utils.ConnectionUtils">
    <property name="dataSource" ref="dataSource"></property>
</bean>
⾃⼰开发的 bean 定义使⽤注解,bean对应
 
例如
 
 <bean id="accountDao" class="com.lagou.edu.dao.impl.JdbcTemplateDaoImpl" scope="singleton" init-method="init" destroy-method="destory">
      <property name="ConnectionUtils" ref="connectionUtils"/>
</bean>
配置注解
 
@Component("accountDao")
public class JdbcAccountDaoImpl implements AccountDao {

 <bean id="transferService" class="com.lagou.edu.service.impl.TransferServiceImpl">
        <!--set+ name 之后锁定到传值的set方法了,通过反射技术可以调用该方法传入对应的值-->
        <property name="AccountDao" ref="accountDao"></property>
    </bean> 

@Component("transferService")
public class TransferServiceImpl implements TransferService {

  <!--事务管理器-->
    <bean id="transactionManager" class="com.lagou.edu.utils.TransactionManager">
        <property name="ConnectionUtils" ref="connectionUtils"/>
    </bean>

 @Component("transactionManager")

public class TransactionManager {

<!--代理对象工厂-->
    <bean id="proxyFactory" class="com.lagou.edu.factory.ProxyFactory">
        <property name="TransactionManager" ref="transactionManager"/>
    </bean> 

 @Component("proxyFactory")

public class ProxyFactory {

 <bean id="connectionUtils" class="com.lagou.edu.utils.ConnectionUtils"></bean> 

 @Component("connectionUtils")

public class ConnectionUtils {

xml 中标签与注解的对应( IoC
 

根据分层不同可以将相应的@Component注解改为@Reposity

@Reposity("accountDao")
public class JdbcAccountDaoImpl implements AccountDao {

DI 依赖注⼊的注解实现⽅式
@Autowired (推荐使⽤)
@Autowired Spring 提供的注解,需要导⼊包
org.springframework.beans.factory.annotation.Autowired
@Autowired 采取的策略为按照类型注⼊。
 
原来的set方法注入
private ConnectionUtils connectionUtils;

public void setConnectionUtils(ConnectionUtils connectionUtils){
    this.connectionUtils=connectionUtils;
}

改造如下

@Autowired
private ConnectionUtils connectionUtils;

 @Autowired按照类型进行注入,如上代码所示,这样装配回去spring容器中找到类型为AccountDao的类,然后将其注⼊进来。这

样会产⽣⼀个问题,当⼀个类型有多个 bean 值的时候,会造成⽆法选择具体注⼊哪⼀个的情况,这个时候我们需要配合着 @Qualififier 使⽤。
 
@Qualififier 告诉 Spring具体去装配哪个对象。这个时候我们就可以通过类型和名称定位到我们想注⼊的对象
 
public class TransferServiceImpl {
@Autowired
@Qualifier ( name = "jdbcAccountDaoImpl" ) //指定具体id
private AccountDao accountDao ;
}

 @Resource

@Resource 注解由 J2EE 提供,需要导⼊包 javax.annotation.Resource

@Resource 默认按照 ByName ⾃动注⼊。
 
public class TransferService {
@Resource
private AccountDao accountDao ;
@Resource ( name = "studentDao" )
private StudentDao studentDao ;
@Resource ( type = "TeacherDao" )
private TeacherDao teacherDao ;
@Resource ( name = "manDao" , type = "ManDao" )
private ManDao manDao ;
}

 

如果同时指定了 name type ,则从 Spring 上下⽂中找到唯⼀匹配的 bean 进⾏装配,找不
到则抛出异常。
如果指定了 name ,则从上下⽂中查找名称( id )匹配的 bean 进⾏装配,找不到则抛出异
常。
如果指定了 type ,则从上下⽂中找到类似匹配的唯⼀ bean 进⾏装配,找不到或是找到多个,
都会抛出异常。
如果既没有指定 name ,⼜没有指定 type ,则⾃动按照 byName ⽅式进⾏装配;
注意 :
@Resource Jdk 11 中已经移除,如果要使⽤,需要单独引⼊ jar
 
<dependency>
<groupId> javax.annotation </groupId>
<artifactId> javax.annotation-api </artifactId>
<version> 1.3.2 </version>
</dependency>

配置识别注解和xml,引入spring-context空间

xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
<!--开启注解扫描,base-package指定扫描的包路径-->
<context:component-scan base-package="com.lagou.edu"/>

再一次进行测试,转账成功,金额正确

1.4 纯注解模式

改造 xm+ 注解模式,将 xml 中遗留的内容全部以注解的形式迁移出去,最终删除 xml ,从 Java 配置类启动
对应注解
@Confifiguration 注解,表名当前类是⼀个配置类
@ComponentScan 注解,替代 context:component-scan

@PropertySource,引⼊外部属性配置⽂件

@Import 引⼊其他配置类
@Value 对变量赋值,可以直接赋值,也可以使⽤ ${} 读取资源配置⽂件中的信息
@Bean 将⽅法返回对象加⼊ SpringIOC 容器
 
用一个SpringConfig配置xml文件
 
package com.lagou.edu;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;

import javax.sql.DataSource;

/**
 * @author 应癫
 */

// @Configuration 注解表明当前类是一个配置类
@Configuration
@ComponentScan({"com.lagou.edu"})
@PropertySource({"classpath:jdbc.properties"})
/*@Import()*/
public class SpringConfig {

    @Value("${jdbc.driver}")
    private String driverClassName;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;


    @Bean("dataSource")
    public DataSource createDataSource(){
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName(driverClassName);
        druidDataSource.setUrl(url);
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);
        return  druidDataSource;
    }
}

测试类中启动spring-ioc容器

 
// 通过读取classpath下的xml文件来启动容器(xml模式SE应用下推荐)
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);

AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");

System.out.println(accountDao);

web容器中启动spring-ioc容器

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>


  <!--告诉ContextloaderListener知道我们使用注解的方式启动ioc容器-->
  <context-param>
    <param-name>contextClass</param-name>
    <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
  </context-param>
  <!--配置启动类的全限定类名-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>com.lagou.edu.SpringConfig</param-value>
  </context-param>
  <!--使用监听器启动Spring的IOC容器-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
</web-app>

测试转账成功,金额正确

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值