软件设计之SSM(2)

软件设计之SSM(2)

路线图推荐:
【Java学习路线-极速版】【Java架构师技术图谱】
尚硅谷新版SSM框架全套视频教程,Spring6+SpringBoot3最新SSM企业级开发
资料可以去尚硅谷官网免费领取

学习内容:

  1. 组件信息声明配置(XML)
  2. 组件依赖注入配置(XML)
  3. IoC容器创建和使用
  4. 组件作用域和周期方法注解
  5. FactoryBean特性及使用
  6. 组件练习知识集合

1. 组件信息声明配置

  1. 学习如何通过定义XML配置文件,声明组件类信息,交给 Spring 的 IoC 容器进行组件管理
  2. 在不考虑反射情况下实例化对象的方式(不同实例化方式对应ioc配置方式也不同):
创建方式描述
无参构造器通过调用类的无参构造函数创建对象。
有参构造器通过调用类的有参构造函数并传入参数来创建对象。
静态工厂使用类的静态方法来创建并返回对象的实例。
非静态工厂通过类的非静态方法创建对象,通常用于复杂的对象创建逻辑。

准备项目

创建一个maven父工程(ssm-spring-part),在其pom.xml导入SpringIoC相关依赖,后续则无需在每个子工程再配置一遍

<dependencies>
    <!--spring context依赖-->
    <!--当你引入Spring Context依赖之后,表示将Spring的基础依赖引入了-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>6.0.6</version>
    </dependency>
    <!--junit5测试-->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.3.1</version>
    </dependency>
</dependencies>

基于无参数构造函数

  1. 准备组件类
package com.atguigu.ioc;


public class HappyComponent {

    //默认包含无参数构造函数

    public void doWork() {
        System.out.println("HappyComponent.doWork");
    }
}
  1. xml配置文件编写(在resources文件夹下创建xml文件)
<!-- 可以使用无参构造函数实例化组件
<bean - 一个组件信息 - 一个组件对象
id 组件的标识 唯一 方便后期读取
class 组件的类的权限定符
将一个组件的类 - 声明两个组件信息 - [默认是单例模式]会实例化两个组件对象-->
    <bean id="happyComponent1" class="com.atguigu.ioc.HappyComponent"></bean>
    <bean id="happyComponent2" class="com.atguigu.ioc.HappyComponent"></bean>

基于静态工厂

  1. 准备组件类
package com.atguigu.ioc;

public class ClientService {
    private static ClientService clientService = new ClientService();
    private ClientService() {}

    public static ClientService createInstance() {

        return clientService;
    }
}
  1. xml配置文件编写(接着之前的xml内容写)
<!--
id 组件的标识
class="工厂类的全限定符:包括它所在的包名和类名"
factory-method = "静态工厂方法"-->
    <bean id="clientService"
          class="com.atguigu.ioc.ClientService"
          factory-method="createInstance"/>

基于实例工厂

  1. 准备组件类(这里ClientServiceImpl类还需要自己创建)
package com.atguigu.ioc;

public class DefaultServiceLocator {

    private static ClientServiceImpl clientService = new ClientServiceImpl();

    public ClientServiceImpl createClientServiceInstance() {
        return clientService;
    }
}
  1. xml配置文件
  <!-- 将工厂类进行ioc配置 -->
    <bean id="serviceLocator" class="com.atguigu.ioc.DefaultServiceLocator">
    </bean>

    <!-- 根据指定工厂对象的实例工厂方法进行实例化组件对象 -->
    <bean id="clientService"
          factory-bean="serviceLocator"
          factory-method="createClientServiceInstance"/>

2、组件依赖注入配置(XML)

  1. 通过配置文件,实现IoC容器中Bean之间的引用(依赖注入DI配置)。

  2. 主要涉及注入场景:基于构造函数的依赖注入基于 Setter 的依赖注入

构造函数单个参数依赖注入

其中UserService的构造函数输入是userDao类型参数,所以此处传递参数使用ref引用其他bean的标识

特性valueref
用途注入基本数据类型或字符串注入其他Bean的引用
类型直接值Bean的ID
示例<property name="name" value="John"/><property name="address" ref="addressBean"/>
使用场景适用于简单属性适用于需要依赖其他Bean的属性
<beans>
  <!-- 引用类bean声明 -->
  <bean id="userService" class="x.y.UserService">
   <!-- 构造函数引用 -->
    <constructor-arg ref="userDao"/>
  </bean>
  <!-- 被引用类bean声明 -->
  <bean id="userDao" class="x.y.UserDao"/>
</beans>

构造函数多个参数依赖注入

constructor-arg标签: name属性指定参数名、index属性指定参数角标、value属性指定普通属性值

方法描述示例
类型注入根据参数类型进行匹配<constructor-arg type="java.lang.String" value="John"/>
索引注入使用index属性指定参数顺序(从0开始)<constructor-arg index="0" value="John"/>
名称注入使用name属性指定参数名称<constructor-arg name="name" value="John"/>
组合使用可以结合使用类型、索引和名称注入<constructor-arg index="0" type="java.lang.String" value="John"/>

基于Setter方法依赖注入

  • 通过调用Setter方法来设置属性,可以在对象创建后再注入依赖。
  • 适用于可选依赖,允许在对象生命周期中更改属性。
  • 使用<property>标签设置属性值,通过调用相应的Setter方法
  • 其中name属性代表set方法标识、ref代表引用bean的标识id、value属性代表基本属性值
  • 假设setMovieFinder方法,对应的name就是movieFinder
<bean id="simpleMovieLister" class="examples.SimpleMovieLister">
  <!-- setter方法,注入movieFinder对象的标识id
       name = 属性名  ref = 引用bean的id值
   -->
  <property name="movieFinder" ref="movieFinder" />

  <!-- setter方法,注入基本数据类型movieName
       name = 属性名 value= 基本类型值
   -->
  <property name="movieName" value="消失的她"/>
</bean>

3、IoC容器创建和使用

容器创建

在Maven项目中,通常在 src/main/resources 目录中放置XML配置文件。Maven会将该目录下的文件复制到 target/classes,所以这些文件会在类路径中

//方式1:实例化并且指定配置文件
//参数:String...locations 传入一个或者多个配置文件
ApplicationContext context = 
           new ClassPathXmlApplicationContext("services.xml", "daos.xml");

组件读取

获取方式使用示例注意事项
根据ID获取HappyComponent happyComponent = (HappyComponent) applicationContext.getBean("bean的id标识");需要进行类型转换,可能导致ClassCastException
根据类型获取HappyComponent happyComponent = applicationContext.getBean(HappyComponent.class);同类型的Bean只能有一个,否则抛出NoUniqueBeanDefinitionException
根据ID和类型获取HappyComponent happyComponent = applicationContext.getBean("bean的id标识", HappyComponent.class);避免了类型转换的问题,确保获取的Bean类型正确。
//方式1: 根据id获取
//没有指定类型,返回为Object,需要类型转化!
HappyComponent happyComponent = 
        (HappyComponent) iocContainer.getBean("bean的id标识");
        
//使用组件对象        
happyComponent.doWork();

//方式2: 根据类型获取
//根据类型获取,但是要求,同类型(当前类,或者之类,或者接口的实现类)只能有一个对象交给IoC容器管理
//配置两个或者以上出现: org.springframework.beans.factory.NoUniqueBeanDefinitionException 问题
HappyComponent happyComponent = iocContainer.getBean(HappyComponent.class);
happyComponent.doWork();

//方式3: 根据id和类型获取
HappyComponent happyComponent = iocContainer.getBean("bean的id标识", HappyComponent.class);
happyComponent.doWork();

4、组件作用域和周期方法注解

周期方法

  • 周期方法要求: 方法命名随意,但是要求方法必须是 public void 无形参列表
  1. 注解方式
  • @PostConstruct:在Bean初始化后自动调用的方法。
  • @PreDestroy:在Bean销毁前自动调用的方法。
@Component
public class MyBean {
    @PostConstruct
    public void init() {
        // 初始化代码
    }

    @PreDestroy
    public void cleanup() {
        // 清理代码
    }
}

  1. XML方式
  • 在XML配置中使用init-methoddestroy-method属性
<bean id="myBean" class="com.example.MyBean" init-method="init" destroy-method="cleanup"/>

组件作用域

作用域描述示例代码
Singleton默认作用域,容器只创建一个实例,所有请求共享。@Scope("singleton")
Prototype每次请求都会创建一个新的实例。@Scope("prototype")
Request每个HTTP请求创建一个新的实例,仅在该请求内有效。@Scope("request")
Session每个HTTP会话创建一个新的实例,仅在该会话内有效。@Scope("session")
GlobalSession用于Portlet应用,每个全局HTTP会话创建一个新的实例。@Scope("globalSession")
Custom自定义作用域,需要实现Scope接口。@Scope("custom")

5、FactoryBean特性及使用

FactoryBean是Spring框架中的一个特殊接口,允许你自定义Bean的创建逻辑。实现FactoryBean接口的类可以控制Bean的实例化过程,使得创建复杂的对象或使用外部资源变得更加灵活。

  1. FactoryBean接口包含以下三个主要方法:
    • T getObject():返回该工厂创建的对象。
    • Class<?> getObjectType():返回该工厂创建的对象的类型。
    • boolean isSingleton():指示创建的对象是否是单例。
  1. FactoryBean实现类
import org.springframework.beans.factory.FactoryBean;

public class MyBeanFactory implements FactoryBean<MyBean> {
    
    @Override
    public MyBean getObject() throws Exception {
        // 创建并返回 MyBean 实例
        return new MyBean("参数");
    }

    @Override
    public Class<?> getObjectType() {
        return MyBean.class;
    }

    @Override
    public boolean isSingleton() {
        return true; // 或者 false,根据需求
    }
}
  1. 配置XML
<!--id getObject返回的对象的标识
class factoryBean标准化工厂类-->
<bean id="myBean" class="com.example.MyBeanFactory"/>

使用&符号前缀引用的是FactoryBean的原始实例

//正常通过FactoryBean创建MyBean对象
MyBean myBean = (MyBean) context.getBean("myBean");
//TODO: FactoryBean工厂也会加入到ioc容器
MyBeanFactory factory = (MyBeanFactory) context.getBean("&myBean");

6、组件练习知识集合

XML内读取配置文件

<context:property-placeholder location="classpath:jdbc.properties"/> 是Spring框架中的一个配置,用于加载位于类路径下的jdbc.properties文件中的属性。它的作用是将该文件中的键值对加载到Spring的环境中,以便在应用程序中使用这些属性。

  • 众所周知,properties文件内存储的是键值对形式数据,在XML引用该文件后可以通过${key}来获取值
 <context:property-placeholder location="classpath:jdbc.properties"/>
 <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${atguigu.url}"/>
        <property name="driverClassName" value="${atguigu.url}"/>
        <property name="username" value="${atguigu.username}"/>
        <property name="password" value="${atguigu.password}"/>
 </bean>

JdbcTemplate

JdbcTemplate 是 Spring 框架中的一个类,主要用于简化 JDBC 操作。它提供了一种简单而高效的方法来执行数据库查询和更新操作,减少了很多繁琐的代码。

功能描述常用方法
简化数据库操作封装 JDBC 连接和异常处理execute(String sql)
执行查询执行 SQL 查询并返回结果query(String sql, RowMapper<T> rowMapper)
执行更新执行 SQL 更新、插入或删除操作update(String sql)
批量更新批量执行多条更新、插入或删除操作batchUpdate(String sql, SqlParameterSource[] batchArgs)
支持参数化查询通过占位符防止 SQL 注入query(String sql, Object[] args, RowMapper<T> rowMapper)
获取单一值查询并返回单个值queryForObject(String sql, Object[] args, Class<T> requiredType)
获取记录计数查询返回结果的行数queryForObject(String sql, Object[] args, Integer.class)
事务支持支持与 Spring 事务管理集成使用 @Transactional 注解
使用命名参数通过命名参数支持 SQL 查询query(String sql, Map<String, ?> paramMap, RowMapper<T> rowMapper)

RowMapper

RowMapper 是 Spring JDBC 中的一个接口,用于将结果集的每一行映射到 Java 对象。它的主要功能是将数据库查询结果转换为更易于处理的对象形式

  • ResultSet rs:表示查询结果集。
  • int rowNum:当前行的索引,从 0 开始。
//匿名内部类用法
List<User> users = jdbcTemplate.query(sql, new RowMapper<User>() {
    @Override
    public User mapRow(ResultSet rs, int rowNum) throws SQLException {
    //
        User user = new User();
        user.setId(rs.getInt("id"));
        user.setName(rs.getString("name"));
        return user;
    }
});

BeanPropertyRowMapper

BeanPropertyRowMapper 是 Spring 框架中用于将 JDBC 查询结果映射到 Java 对象的一个便利类。它通过反射根据列名自动填充对象的属性,简化了手动映射的过程。使用时,只需提供目标类的类型,它会根据列名匹配类的属性。

  • 例如,如果数据库中的列名是 name,那么 BeanPropertyRowMapper 会将结果集中的 name 列映射到 Java 对象的 name 属性。这使得数据库操作更加简洁,代码更易于维护。
//一步搞定
List<User> users = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));

总体框架

层次类名成员变量描述
ControllerStudentControllerprivate StudentService studentService;控制器中需要调用 Service 层,因此引入对应的 Service 实现类作为成员变量。
ServiceStudentServiceImplprivate StudentDao studentDao;Service 实现类中需要调用 DAO 层,因此引入对应的 DAO 实现类作为成员变量。
StudentService定义 Service 的行为,不包含具体实现。
DAOStudentDaoImplprivate JdbcTemplate jdbcTemplate;DAO 实现类中使用 JdbcTemplate 来执行数据库操作,因此需要将其作为成员变量。
StudentDao定义数据访问的行为,用于 CRUD 操作。
POJOStudentint id; String name; int age; ...表示数据库表中的一条记录,通常只包含属性及其 getter/setter 方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值