Spring6

最简单的Spring程序

1. Spring的基本结构

在一个最简单的Spring程序中,通常包含以下几个部分:

  • Bean:Spring管理的对象,通常是POJO(Plain Old Java Object)。
  • ApplicationContext:Spring的IOC(Inversion of Control,控制反转)容器,负责管理Bean的创建和依赖注入。
  • 配置文件:Spring XML配置文件或者基于注解的配置,Spring通过这些配置来初始化并管理Bean。

基本示例

代码结构:
css 复制代码
src
└── main
    └── java
        ├── com.example
        │   ├── AppConfig.java
        │   ├── UserService.java
        │   └── Main.java
    └── resources
        └── beans.xml
1. 创建Bean(POJO)

这是一个最简单的业务类 UserService,模拟一个服务层对象。

java 复制代码
package com.example;

public class UserService {
    public void saveUser() {
        System.out.println("User saved!");
    }
}
2. 配置Bean(XML配置)

在Spring中,beans.xml 是用来定义Bean的配置文件。我们在这里定义 UserService 对象。

XML 复制代码
<!-- beans.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.xsd">

    <!-- 定义一个id为userServiceBean的bean,类为UserService 注意这里Class后面是全限定类名 -->
    <bean id="userServiceBean" class="com.example.UserService"/>
</beans>
3. 使用Spring容器获取Bean

Main.java 中,我们通过Spring的 ApplicationContext 容器来获取 UserService Bean 并调用其方法。

java 复制代码
package com.example;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        // 加载Spring配置文件并初始化容器
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        // 获取userServiceBean
        UserService userService = context.getBean("userServiceBean", UserService.class);

        // 调用UserService的方法
        userService.saveUser();
    }
}
详细解释
1.ClassPathXmlApplicationContext("beans.xml")
java 复制代码
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
  • ClassPathXmlApplicationContextApplicationContext 的一个实现类,负责从类路径下加载指定的XML文件并初始化Spring容器。
  • 参数 beans.xml
    • 文件名 :这个参数指定了配置文件的名称。在这个例子中**,beans.xml 是Spring的配置文件,定义了所有Spring管理的Bean。**
    • 路径要求文件 beans.xml 必须位于类路径下(通常是在 src/main/resources 目录中)。Spring会自动查找类路径中的这个文件,并根据配置加载Bean。
    • 文件类型beans.xml 是一个标准的XML文件,包含Spring应用的配置,包括Bean的定义、依赖注入等信息。

注意事项

  • ClassPathXmlApplicationContext 只能从类路径中加载文件,确保 beans.xml 在类路径中能够被找到。如果文件不在类路径中,可以使用其他实现类如 FileSystemXmlApplicationContext 从文件系统中加载配置。
2.context.getBean("userServiceBean", UserService.class)
java 复制代码
UserService userService = context.getBean("userServiceBean", UserService.class);
  • getBean(String name, Class<T> requiredType) :这是 ApplicationContext 接口的一个方法,用来从Spring容器中获取一个特定的Bean。这个方法根据指定的Bean名称和类型从容器中返回已初始化的Bean对象。
参数详解:

1. name("userServiceBean")

  • 这是你在Spring配置文件(beans.xml)中定义的Bean的ID。

  • 例如,在beans.xml中,你可能有这样的Bean定义:

    XML 复制代码
    <bean id="userServiceBean" class="com.example.UserService"/>

    在这里,userServiceBean 是这个 UserService Bean 的ID,必须和配置文件中的 id 保持一致。如果ID不匹配,Spring会抛出 NoSuchBeanDefinitionException

2. requiredTypeUserService.class

  • 这是Bean的类型,要求Spring返回的Bean对象必须能够被转换为这个类型。UserService.class 是目标Bean的类型,即类 UserService

  • 这个类型检查是为了确保Spring容器返回的Bean符合预期的类型。如果Bean的实际类型和这里指定的类型不兼容,会抛出 BeanNotOfRequiredTypeException

  • requiredType 参数可以省略,比如:

    java 复制代码
    UserService userService = (UserService) context.getBean("userServiceBean");
    • 但是这种方式需要手动进行类型转换(即强制类型转换),不如直接使用 getBean 的泛型版本安全,因为后者会自动进行类型检查。

注意事项:

  • name 必须与Spring配置文件中的 idname 属性一致。
  • requiredType 必须是Bean的实际类型或其父类/接口,如果类型不匹配会抛出异常

Spring对IoC的实现

IoC 控制反转

  • 控制反转是一种思想。

  • 控制反转是为了降低程序耦合度,提高程序扩展力,达到OCP原则,达到DIP原则。

  • 控制反转,反转的是什么?

    • 将对象的创建权利交出去,交给第三方容器负责。

    • 将对象和对象之间关系的维护权交出去,交给第三方容器负责。

  • 控制反转这种思想如何实现呢?

    • DI(Dependency Injection):依赖注入

依赖注入:

依赖注入实现了控制反转的思想。 Spring通过依赖注入的方式来完成Bean管理的。 Bean管理说的是:Bean对象的创建,以及Bean对象中属性的赋值(或者叫做Bean对象之间关系的维护)。

  • 依赖指的是对象和对象之间的关联关系。

  • 注入指的是一种数据传递行为,通过注入行为来让对象和对象产生关系。

依赖注入常见的实现方式包括两种:

  • 第一种:set注入

  • 第二种:构造注入

set注入:

set注入,基于set方法实现的,底层会通过反射机制调用属性对应的set方法然后给属性赋值。这种方式要求属性必须对外提供set方法

什么是 Set注入?

Setter 注入是一种常用的依赖注入方式,通过Spring容器调用对象的 setter 方法来完成依赖的注入。这种方式常用于当依赖是可选的,或者对象在创建后可以被修改时。与构造器注入相比,Setter 注入的灵活性更高。注意:在实例化对象之后才进行set注入。

Set 注入的工作原理

  • Bean定义 :在Spring配置文件(XML或注解)中,定义目标Bean,并使用 property 标签或注解指明哪个属性需要注入。
  • Spring容器调用Setter方法 :在创建Bean实例后,Spring容器会自动调用相应的 setter 方法,将依赖对象注入到Bean中。

代码示例

以下是一个简单的 Setter 注入示例:

1. 创建依赖类 UserDao
java 复制代码
package com.example;

public class UserDao {
    public void save() {
        System.out.println("Saving user data...");
    }
}
2. 创建服务类 UserService

UserService 依赖于 UserDao,并使用 Setter 方法来注入这个依赖。

java 复制代码
package com.example;

public class UserService {
    private UserDao userDao;

    // Setter方法,用于注入依赖
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void saveUser() {
        userDao.save();
        System.out.println("User saved by UserService");
    }
}
3. Spring XML配置(beans.xml

在Spring配置文件中,使用 <property> 标签来实现 Setter 注入。

XML 复制代码
<!-- beans.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.xsd">

    <!-- 定义UserDao对象 -->
    <bean id="userDaoBean" class="com.example.UserDao" />

    <!-- 定义UserService对象,并通过Setter方法注入UserDao依赖 -->
    <bean id="userServiceBean" class="com.example.UserService">
        <!-- 注入依赖,通过setUserDao方法 -->
        <property name="userDao" ref="userDaoBean" />
    </bean>

</beans>
4. 使用 ApplicationContext 获取 UserService Bean
java 复制代码
package com.example;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        // 加载Spring配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        // 获取userServiceBean
        UserService userService = context.getBean("userServiceBean", UserService.class);

        // 调用UserService的方法
        userService.saveUser();
    }
}

4. 关键知识点

1. property 标签
  • 在Spring的XML配置文件中,<property> 标签用于指定要注入的属性。

  • name 属性对应Bean类中的 setter 方法的属性名。

  • ref 属性指定要注入的依赖Bean的ID。

    XML 复制代码
    <property name="userDao" ref="userDaoBean" />
  • name :对应 UserService 类中的 setUserDao 方法中的 userDao 属性(set方法的方法名,去set,然后把剩下的单词首字母变小写)。

  • ref :引用了 userDaoBean,这个Bean在Spring配置文件中定义(指定的是要注入的bean的id)。

2. Spring的 Setter 注入流程
  • 创建Bean :Spring首先会根据配置文件中的 <bean> 元素创建对象实例 (如 UserService)。
  • 调用 Setter 方法 :对象实例创建后,Spring会根据 <property> 标签的配置,调用相应的 setter 方法(如 setUserDao),将依赖对象注入到目标对象中。

构造注入:

构造器注入是通过构造函数来注入对象的依赖。Spring会根据构造函数的参数来识别需要注入的依赖,并在实例化对象时注入这些依赖。注意和set注入不同,set注入是实例化对象之后。

3. 代码示例

1. 依赖类 UserDao
java 复制代码
package com.example;

public class UserDao {
    public void save() {
        System.out.println("UserDao: Saving user data...");
    }
}
2. 服务类 UserService(使用构造器注入)

UserService 依赖 UserDao,并通过构造函数注入 UserDao 对象。

java 复制代码
package com.example;

public class UserService {
    private UserDao userDao;

    // 构造器,用于注入依赖
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }

    public void saveUser() {
        userDao.save();
        System.out.println("UserService: User saved.");
    }
}
3. Spring XML配置(beans.xml

在Spring配置文件中,通过 constructor-arg 元素来配置构造器注入。

单个参数
XML 复制代码
<!-- beans.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.xsd">

    <!-- 定义UserDao对象 -->
    <bean id="userDao" class="com.example.UserDao" />

    <!-- 定义UserService对象,通过构造器注入UserDao依赖 -->
    <bean id="userService" class="com.example.UserService">
        <constructor-arg ref="userDao"/>
    </bean>

</beans>
多个参数

CustomerService:

java 复制代码
package spring6.service;

import spring6.Dao.UserDao;

public class CustomerService {
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public CustomerService(UserDao userDao2) {
        this.userDao = userDao2;
    }

    public void save(){
        userDao.insert();
    }
}
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.xsd">

    <bean id="userDaoBean2" class="spring6.Dao.UserDao">

</bean>
    <bean id="customerService" class="spring6.service.CustomerService">
<!--        <property name="userDao2" ref="userDao2"/>-->
<!--        index属性指定参数下标,第一个参数是0,第二个参数是1,第三个参数是2,以此类推-->
<!--        ref属性用来指定注入的bean的id-->
        <constructor-arg    index="0" ref="userDaoBean2"/>
    </bean>

    <bean id="customerService2" class="spring6.service.CustomerService">
<!--        根据构造方法参数的名字进行注入-->
        <constructor-arg name="userDao2" ref="userDaoBean2"/>
    </bean>
</beans>
  1. 使用 ApplicationContext 获取 UserService Bean
java 复制代码
package com.example;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        // 加载Spring配置文件并初始化容器
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        // 获取userService对象
        UserService userService = context.getBean("userService", UserService.class);

        // 调用UserService的方法
        userService.saveUser();
    }
}

4. 关键知识点

1. constructor-arg 标签
  • constructor-arg 标签用于Spring的XML配置中,用来配置构造器注入。
2. ref属性
单个参数

ref 属性指定要注入的Bean的ID,这个引用会在目标类的构造函数中被传入。

XML 复制代码
<constructor-arg ref="userDao"/>
多个参数
1. index 属性

index 属性用于明确指定构造函数参数的顺序位置。Spring会根据构造函数中参数的位置来注入对应的Bean。这种方式在构造函数有多个参数时非常直观和有效,尤其是多个参数类型相同的情况下。

代码中的示例:

XML 复制代码
<constructor-arg index="0" ref="userDaoBean2"/>
  • index="0" :表示将 userDaoBean2 注入到构造函数的第一个参数位置。
  • 如果构造函数有多个参数,index 指定了注入的顺序。0 表示第一个参数,1 表示第二个参数,依此类推。
2. name 属性

name 属性用于通过参数的名称(构造函数中声明的参数名)来注入Bean。Spring通过反射机制获取构造函数的参数名称,并根据这个名称来进行依赖注入。

XML 复制代码
<constructor-arg name="userDao2" ref="userDaoBean2"/>
  • name="userDao2" :表示将 userDaoBean2 注入到名为 userDao2 的构造函数参数中。
  • 这种方式要求构造函数的参数名称必须与 name 属性的值匹配。
举例 :

1. 构造函数基础

构造函数是一个类的特殊方法,用于在创建该类的对象时进行初始化。在Java中,一个类可以有多个参数的构造函数,这意味着你在创建对象时可以传递多个值进行初始化。

例如,下面的 CustomerService 类的构造函数有两个参数:

java 复制代码
public class CustomerService {
    private UserDao userDao;
    private OrderDao orderDao;

    // 构造函数有两个参数
    public CustomerService(UserDao userDao, OrderDao orderDao) {
        this.userDao = userDao;
        this.orderDao = orderDao;
    }
}

这个构造函数有两个参数:UserDaoOrderDao。在创建 CustomerService 对象时,必须同时提供这两个依赖。

2. Spring 中的多个构造函数参数

当你在Spring中使用构造器注入时,如果你的类的构造函数有多个参数,你需要告诉Spring应该如何注入这些依赖。Spring有多种方式处理这些参数,比如通过参数的顺序、参数的类型或者通过参数的名称。

示例:多个构造函数参数的构造器注入

java 复制代码
public class CustomerService {
    private UserDao userDao;
    private OrderDao orderDao;

    // 构造函数有两个参数
    public CustomerService(UserDao userDao, OrderDao orderDao) {
        this.userDao = userDao;
        this.orderDao = orderDao;
    }
}

在这个示例中,CustomerService 的构造函数需要两个对象:UserDaoOrderDao

3. Spring XML 配置 - 指定多个构造函数参数

使用 index 属性指定参数顺序

XML 复制代码
<bean id="userDao" class="com.example.UserDao"/>
<bean id="orderDao" class="com.example.OrderDao"/>

<bean id="customerService" class="com.example.CustomerService">
    <constructor-arg index="0" ref="userDao"/>
    <constructor-arg index="1" ref="orderDao"/>
</bean>

使用 name 属性指定参数名称

XML 复制代码
<bean id="userDao" class="com.example.UserDao"/>
<bean id="orderDao" class="com.example.OrderDao"/>

<bean id="customerService" class="com.example.CustomerService">
    <constructor-arg name="userDao" ref="userDao"/>
    <constructor-arg name="orderDao" ref="orderDao"/>
</bean>

在这个配置中:

  • name="userDao"name="orderDao" 表示注入的对象是根据构造函数中的参数名称匹配的。

在开发中如果 需要自动实例化dao包中的对象的话到底应该怎么做?

通常**,我们需要自动实例化dao包中的对象,需要在Service层中使用Dao中的类**。如果不使用spring的话,通常需要在 Service 层手动编写对象实例化的代码,如 new DaoClass()。这种方式虽然简单直观,但在复杂的应用中,当对象之间的依赖关系较多时,手动管理这些依赖关系将变得困难,并且会导致代码难以维护和扩展。

如果运用spring,spring中的spring.xml中可以实现自动实例化,来自动管理对象的创建和依赖关系,这样就能方便一点

所以说spring.xml到底应该如何配置呢?

1. DAO类的实例化

首先,你需要在XML文件中为DAO类定义一个Bean。假设你有一个名为UserDao的DAO类:

XML 复制代码
<bean id="userDao" class="com.example.dao.UserDao"/>

这样,Spring就会自动实例化一个UserDao对象,并将其放入Spring容器中,ID为userDao

2. 在Service中注入DAO类

接下来,在Service类中,你需要通过依赖注入的方式将UserDao传递给Service类。假设你的Service类是UserService,并且有一个UserDao类型的属性(通常是通过setter方法或者构造方法来注入的)。

2.1 通过Setter注入

如果UserService类中有setUserDao(UserDao userDao)方法,XML配置可以这样写:

XML 复制代码
<bean id="userService" class="com.example.service.UserService">
    <property name="userDao" ref="userDao"/>
</bean>
  • <property> :表示为userService Bean的属性设置值。
  • name :表示UserService类中的userDao属性。
  • ref :引用了Spring容器中ID为userDao的Bean。
2.2 通过构造方法注入

如果你希望通过构造方法注入UserDao,并且UserService类有一个构造方法是public UserService(UserDao userDao),XML配置可以这样写:

XML 复制代码
<bean id="userService" class="com.example.service.UserService">
    <constructor-arg ref="userDao"/>
</bean>
  • <constructor-arg>:表示构造方法参数的引用。
  • ref :表示注入的Bean,即userDao

3. Service与DAO的关系总结

  • DAO层负责直接与数据库进行交互,如增删改查操作。
  • Service层负责业务逻辑处理,它会调用DAO层的方法来处理数据库中的数据。

在Spring中,通过依赖注入,Service层不需要自己去创建DAO层的对象,Spring会自动实例化DAO层,并将它注入到Service层。

相关推荐
神仙别闹16 分钟前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭40 分钟前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫1 小时前
泛型(2)
java
超爱吃士力架1 小时前
邀请逻辑
java·linux·后端
南宫生1 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石1 小时前
12/21java基础
java
李小白661 小时前
Spring MVC(上)
java·spring·mvc
GoodStudyAndDayDayUp2 小时前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea
装不满的克莱因瓶2 小时前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb
n北斗2 小时前
常用类晨考day15
java