SSM框架学习笔记(1)——Spring

1. Spring

分层的Java SE/EE应用full-stack轻量级开源框架,以Ioc(反转控制)和AOP(面向切面编程)为内核。

1.1 Spring开发步骤

  • 导入Spring的Maven坐标,重新加载项目

    在这里插入图片描述

    在这里插入图片描述

  • 编写Dao接口和实现类

    在这里插入图片描述

    在这里插入图片描述

  • 创建Spring核心配置文件(xml配置文件)

    在resources目录下创建applicationContext.xml文件

    在这里插入图片描述

  • 在Spring配置文件中配置UserDaoImpl

    在这里插入图片描述

  • 使用Spring的API获得Bean实例

    在这里插入图片描述

在这里插入图片描述

1.2 Spring配置文件

1.2.1 Bean标签基本配置

用于配置对象交给Spring创建,默认情况下调用无参构造函数,若没有无参构造函数则不能创建成功。

基本属性:

  • id:Bean实例在Spring容器中的唯一标识。
  • class:Bean的全限定名称。

1.2.2 Bean标签范围配置

scope:指对象的作用范围。

  • singleton(默认值):
    • Bean的实例化个数:1个。即在容器中只有一个对象,若创建多个对象则地址相同。
    • Bean的实例化时机:当Spring的核心文件被加载时,实例化配置Bean的实例。
    • Bean的生命周期:
      • 对象创建:应用被加载时。
      • 对象运行:容器存在的时候。
      • 对象销毁:应用卸载,销毁容器时。
  • prototype:
    • Bean的实例化个数:多个。即在容器中只有一个对象,若创建多个对象则地址不同。
    • Bean的实例化时机:调用getBean()方法时。
    • Bean的生命周期:
      • 对象创建:创建新的对象实例时。
      • 对象运行:对象在使用中,就一直存在。
      • 对象销毁:当对象长时间不使用时,被Java的垃圾回收器回收。

1.2.3 Bean生命周期配置

  • init-method:指定类中的初始化方法名称。

  • destroy-method:指定类中销毁方法名称。

    在这里插入图片描述

    在这里插入图片描述

1.2.4 Bean实例化三种方式

  • 无参构造方法实例化(默认)

  • 工厂静态方法实例化

    在这里插入图片描述

    在这里插入图片描述

  • 工厂实例方法实例化(先获取工厂对象,再调用方法)

    在这里插入图片描述

    在这里插入图片描述

1.2.5 Bean的依赖注入

依赖注入(Dependency Injection)是Spring框架核心IOC的具体体现。

把dao和service之间的关系配置到容器中,降低其依赖关系(解耦)。使用Spring来维护业务层和持久层的依赖关系。

  • Bean的依赖注入方式

    • set方法注入

      • 一般方法

        <bean id="userService" class="com.kepler.service.impl.UserServiceImpl">
            <!-- 把容器中的 UserDao 通过 UserService 内部的 setUserDao 方法注给 UserService -->
            <!-- 第一个"userDao"是service内部对象的属性名,第二个表示应用容器中id为"userDao"的Bean -->
            <property name="userDao" ref="userDao"></property>
        </bean>
        
      • P命名空间

        xmlns:p="http://www.springframework.org/schema/p"
        
        <!-- 修改注入方式 -->
        <bean id="userService" class="com.kepler.service.impl.UserServiceImpl" p:userDao-ref="userDao"></bean>
        
    • 有参构造注入

      在这里插入图片描述

      <bean id="userService" class="com.kepler.service.impl.UserServiceImpl">
              <constructor-arg name="userDao" ref="userDao"></constructor-arg>
      </bean>
      
  • Bean的依赖注入的数据类型

    • 普通数据类型
    • 引用数据类型(Bean引入)
    • 集合数据类型

1.2.6 引入其他配置文件(分模块开发)

​ 实际开发中,Spring的配置内容非常多,这就导致Spring配置繁杂且体积庞大。所以,可以将部分配置拆解到其他配置文件中,而在Spring主配置文件通过 import 标签进行加载。

<import resources="applicationContext-xxx.xml"/>

1.2.7 Spring 的重点配置

<bean>标签
	id属性:在容器中Bean实例的唯一标识
	class属性:要实例化的Bean的全限定名
	scope属性:Bean的作用范围,常用是Singleton(默认)和prototype
	<property>标签:属性注入
		name属性:属性名称
		value属性:注入的普通属性值
		ref属性:注入的对象引用值
		<list>标签
		<map>标签
		<properties>标签
	<constructor-arg>标签
<import>标签:导入其他的Spring的分文件

1.3 Spring相关API

1.3.1 ApplicationContext

ApplicationContext:接口类型,代表应用上下文,可以通过其实例获得Spring容器中的Bean对象。

  • ApplicationContext继承体系

    在这里插入图片描述

  • ApplicationContext的实现类

    • ClassPathXmlApplicationContext 从类的根路径下加载配置文件( 推荐)
    • FileSystemXmlApplicationContext 从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置
    • AnnotationConfigApplicationContext 当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解

1.3.2 getBean()方法

  • getBean(String name)

    表示根据Bean的id从容器中获得Bean实例,返回是Object,需要强转。

  • getBean(Class requiredType)

    表示根据类型从容器中匹配Bean实例,当容器中相同类型的Bean有多个时,此方法会报错。

ApplicationContext applicationContext = new 
ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService1 = (UserService) applicationContext.getBean("userService");
UserService userService2 = applicationContext.getBean(UserService.class);

1.3 Spring配置数据源

1.3.1 数据源(连接池)的作用和原理

  • 数据源(连接池)用于提高程序性能
  • 事先实例化数据源,初始化部分连接资源
  • 使用连接时从数据源中获取
  • 使用完毕后将连接资源归还给数据源
    常见数据源(连接池):DBCP、C3P0、BoneCp、Druid等

1.3.2 数据源的开发步骤

  • 导入数据源坐标和数据库驱动坐标
<dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <version>5.1.47</version>
 </dependency>
 <dependency>
     <groupId>c3p0</groupId>
     <artifactId>c3p0</artifactId>
     <version>0.9.1.2</version>
 </dependency>
 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>druid</artifactId>
     <version>1.1.10</version>
 </dependency>
 <dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>4.12</version>
     <scope>test</scope>
 </dependency>
  • 创建数据源对象(使用Spring配置)
    ① 导入坐标
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.16</version>
</dependency>

② 创建Spring配置文件
在xml文件中加载properties文件
jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root
<?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: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">

    <!--  加载外部的 properties文件  -->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="jdbc.username"/>
        <property name="password" value="jdbc.password"/>
    </bean>

</beans>

③ 测试Spring容器产生数据源对象

@Test
// 测试Spring容器产生数据源对象
public void test4() throws Exception {
    ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
    DataSource dataSource = app.getBean(DataSource.class);
    Connection connection = dataSource.getConnection();
    System.out.println(connection);
    connection.close();
}
  • 设置数据源的基本连接数据
  • 使用数据获取连接资源和归还连接资源

1.4 Spring 注解开发

1.4.1 Spring 原始注解

在这里插入图片描述

  • 使用注解开发时,需要在applicationContext.xml中配置组件扫描,作用是指定哪个包及其子包下的Bean需要进行扫描以便识别使用注解配置的类、字段和方法
<!--  配置组件扫描  -->
<context:component-scan base-package="com.kepler"/>
  • 用注解替代配置
// <bean id="userDao" class="com.kepler.dao.Impl.UserDaoImpl"></bean>
//@Component("userDao")
@Repository("userDao")
public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("save running...");
    }
}
//<bean id="userService" class="com.kepler.service.Impl.UserServiceImpl">
//@Component("userService")
@Service("userService")
public class UserServiceImpl implements UserService {

    // <property name="userDao" ref="userDao"></property>
    @Autowired  // 自动注入,按照数据类型从Spring容器中进行注入
    @Qualifier("userDao") // 按照id名称从容器中纪念性匹配,写要被注入的 bean的id,但此处需结合@Autowired一起使用
    private UserDao userDao;

    @Override
    public void save() {
        userDao.save();
    }
}

1.4.2 Spring 新注解

在这里插入图片描述

package com.kepler.config;

import org.springframework.context.annotation.*;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

// 标识该类时Spring的核心配置类
@Configuration
//<context:component-scan base-package="com.kepler"/>
@ComponentScan("com.kepler")
//<import resource=""/>
@Import({DataSourceConfiguration.class})
public class SpringConfiguration {

}
package com.kepler.config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

//<context:property-placeholder location="classpath:jdbc.properties"/>
@PropertySource("classpath:jdbc.properties")
public class DataSourceConfiguration {

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

    @Bean("dataSource") // Spring 会将当前方法的返回值以指定名称存储到 Spring 容器中
    public DataSource getDataSource () throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(driver);
        dataSource.setJdbcUrl(url);
        dataSource.setUser(username);
        dataSource.setPassword(password);
        return dataSource;
    }
}
package com.kepler.web;

import com.kepler.config.SpringConfiguration;
import com.kepler.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class UserController {
    public static void main(String[] args) {
        ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class);
        UserService userService = app.getBean(UserService.class);
        userService.save();
    }
}

1.5 Spring 整合 Junit

1.5.1 Spring集成Junit步骤

  • 导入Spring集成Junit的坐标
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.3.16</version>
</dependency>
  • 使* 用@Runwith注解替换原来的运行期
  • 使用@ContextConfiguration指定配置文件或配置类
  • 使用@Autowired注入需要测试的对象
  • 创建测试方法进行测试
package com.kepler.test;

import com.kepler.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
// @ContextConfiguration("classpath:applicationContext.xml") // 加载配置文件
@ContextConfiguration(classes = {SpringConfiguration.class}) // 全注解形式
public class SpringJunitTest {

    @Autowired
    private UserService userService;

    @Test
    public void test1() {
        userService.save();
    }
}

1.6 Spring 集成 Web 环境

1.6.1 ApplicationContext应用上下文获取方式

应用上下文对象是通过new ClassPathXmlApplicationContext(Spring配置文件)方式获取的,但每次从容器中获得Bean时,都要编写此代码,配置文件被加载多次,应用上下文对象创建多次。

在Web项目中,可以使用ServletContextListener监听Web应用的启动,我们可以在Web应用启动时,就加载Spring的配置文件,创建应用上下文对象ApplicationContext,在其存储到最大的域servletContext域中,即可在任意位置从域中获得应用上下文ApplicationContext对象了。

  • 创建监听器
package com.kepler.listener;

import com.kepler.Service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class ContextLoaderListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext servletContext = sce.getServletContext();
        // 读取 web.xml中的全局参数
        String contextConfiguration = servletContext.getInitParameter("contextConfiguration");
        ApplicationContext app = new ClassPathXmlApplicationContext(contextConfiguration);
        // 将 Spring 的应用上下文对象存储到ServletContext中
        servletContext.setAttribute("app", app);
        System.out.println("Spring 容器创建完毕...");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        ServletContextListener.super.contextDestroyed(sce);
    }
}

  • 配置web.xml
<!-- 全局初始化参数  -->
<context-param>
    <param-name>contextConfiguration</param-name>
    <param-value>applicationContext.xml</param-value>
</context-param>
    
<!--  配置监听器  -->
<listener>
    <listener-class>com.kepler.listener.ContextLoaderListener</listener-class>
</listener>
package com.kepler.listener;

import org.springframework.context.ApplicationContext;

import javax.servlet.ServletContext;

public class WebApplicationContextUtils {

    public static ApplicationContext getWebApplicationContext(ServletContext servletContext) {
        return (ApplicationContext) servletContext.getAttribute("app");
    }
}

  • 修改doGet
package com.kepler.web;

import com.kepler.Service.UserService;
import com.kepler.listener.WebApplicationContextUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class UserServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
//        ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
        ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
        UserService userService = app.getBean(UserService.class);
        userService.save();
    }
}

1.6.2 Spring 提供获取应用上下文的工具

以上分析不用手动实现,Spring提供一个监听器ContextLoaderListener就是对上述功能的封装,该监听器内部加载Spring配置文件,创建应用上下文对象,并存储到ServletContext域中,提供了一个客户端工具WebApplicationContextUtils供使用者获得应用上下文对象

  • 导入spring-web依赖
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.3.10</version>
</dependency>
  • 在web.xml中配置ContextLoaderListener监听器(导入spring-web坐标)
<!-- 全局初始化参数  -->
<context-param>
    <param-name>contextConfiguration</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>

<!--  配置监听器  -->
<listener>
    <listener-class>com.kepler.listener.ContextLoaderListener</listener-class>
</listener>
  • 使用WebApplicationContextUtils获得上下文对象ApplicationContext
package com.kepler.web;

import com.kepler.Service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class UserServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
        UserService userService = app.getBean(UserService.class);
        userService.save();
    }
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值