美文网首页
Spring最佳教学教程入门笔记

Spring最佳教学教程入门笔记

作者: 我问你瓜保熟吗 | 来源:发表于2022-01-15 09:52 被阅读0次

一、Spring简介

Spring 是由 Rod Johnson 2004 组织和开发的一个分层的 Java SE/EE fu stack (一站式)轻量级开源框架,Spring 可以被看作是一个大型工厂,这个工厂的作用就是生产和管理 Spring 容器中的Bean。它以 loC (Inversion of Control ,控制反转)和 AOP ( Aspect Oriented Programming , 面向切面编程)为内核,Spring 致力于 Java EE 应用各层的解决方案,在表现层它提供了 Spr ng MVC 以及与 Struts 框架的整合功能;在业务逻辑层可以管理事务 记录日志等;在持久层可以整合 MyBatis Hibernate JdbcTemplate 等。在 Spring 中,认为一切 Java 类都是资源,而资源都是类的实例对象(Bean),容纳并管理这些 Bean 的是 Spring 所提供的 IoC 容器,所以 Spring 是一种基于 Bean 的编程。

  • 控制反转(IoC ):当某个 Java 对象(调用者)需要调用另一个 Java 对象(被调用者,即被依赖对象)时, 在传统模式下,调用者通常会采用 "new 被调用者"的代码方式来创建对象,这种方式会导致调用者与被调用者之间的捐合性增加,不利于后期项目的升级和维。在使用 Spring 框架之后,对象的实例不再由调用者来创建,而是由 Spring 容器来创建,Spring 容器会负责控制程序之间的关系,而不是由调用者的程序代码直接控制 这样,控制权由应用代码转移到了 Spring 容器,控制权发生了反转,这就是 Spring 的控制反转。
  • **依赖注入( Dependency Injection ,简称 DI) **:与控制反转 (loC) 的含义相同,只不过这两 个称呼是从两个角度描述的同一个概念 对Spring 容器的角度来看, Spring 容器负责将被依赖对象赋值给调用者的成员变量,这相当于为调用者注入了它依赖的实例,这就是 Spring 的依赖注入。依赖注入的作用就是在使用 Spring 框架创建对象时,动态地将其所依赖的对象注入Bean组件中。

  • AOP:

BeanFactory 就是一千管理 Bean 的工厂,它主要负责初始化各种 Bean ,并调用它们的生命周期方法,ApplicationContext是BeanFactory 的子接口,也被称为应用上下文,包含了BeanFactory 的所有功能。

二、体系架构

image.pngimage.png

1、核心容器

Spring 的核心容器是其他模块建立的基础,由 Beans 模块、Core 核心模块、Context 上下文模块和 SpEL 表达式语言模块组成

  • Core 核心模块:提供了 Spring 框架的基本组成部分,包括 loC 和 DI 功能 ,是其他组件的基本核心。
  • Beans 模块:它包含访问配置文件、创建和管理 Bean 以及进行IOC/DI操作相关的所有类
  • Context 上下文模块:立在 Core Beans 模块的基础之上,它是访问定义和配置的任 何对象的媒介 其中 ApplicationConte 接口是上下文模块的焦点
  • SpEL 模块:是 Spring 后新增的模块,它提供了 Spring Expression Language 支持,是运行时查询和操作对象图的强大的表达式语言

2、数据访问/集成

  • JDBC 模块:提供了一个 JDBC 的抽象层,大幅度地减少了在开发过程中对数据库操作的编码
  • Transactions 事务模块:支持对实现特殊接口以及所有 POJO 类的编程和声明式的事 务管理

3、web层

  • Web 模块:提供了基本的 Web 开发集成特性,例如: 多文件上传功能 使用 Servlet 听器来初始化 loC 容器以及 Web 应用上下文
  • Servlet 模块:也称为 Spring-webmvc 模块,包含了 Spring 的模型一视图一控制器(MVC) REST Web Services 实现的 Web 应用程序

4、其它模块

  • AOP 模块:提供了面向切面编程实现,允许定义方法拦截器和切入点,将代码按照功能

进行分离,以降低搞合性

  • Aspects 模块:提供了与 AspectJ 的集成功能, AspectJ 是一个功能强大且成熟的面向切

面编程 (AOP) 框架

  • Test 模块:提供了对单元测试和集成测试的支持

二、快如搭建

1. 依赖

        <!--单独引入Spring的四个核心包-->
                <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.3.14</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.14</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.3.14</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>5.3.14</version>
        </dependency>

                <!--引入spring-context包会自动引入Spring的四个核心包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.13</version>
        </dependency>

                <!--引入此包会自动引入Spring的四个核心包+spring-aop+spring-web-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.3.14</version>
        </dependency>

2、编写Spring配置文件

idea在resources里创建Spring Config xml文件applicationContext.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">

    <!--Spring管理创建的对象,在Spring里都成为Bean,需要在这里进行注册-->
    <bean id="hello" class="com.example.spring.pojo.Hello">
        <property name="name" value="Spring"/>
    </bean>

</beans>

3、初始化Spring容器、实例化bean

    public static void main(String[] args) {
      
        // 获取ApplicationContext,拿到Spring的容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        // 将需要Spring管理创建对象的类在配置文件中注册,然后在需要用的地方直接get
        Hello name = (Hello) context.getBean("hello");
        System.out.println(name.toString());
    }

三、详解 Spring容器初始化

Java 项目中,会采用通过 ClassPathXmlApplicationContext 类来实例化ApplicationContext 容器的方式。

// 1.初始化 spring 容器,加载配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 2.通过容器获取Hello实例
Hello name = (Hello) context.getBean("hello");

在 Web 项目中, ApplicationContext 容器的实例化工作会交由 Web 服务器来完成 Web 服务器实例化ApplicationContext 容器时,通常会使用基于ContextLoader Li stener 实现的方式,此种方式只需要在web.xml` 中添加如下代码

<!… 指定 Spring 配置文件的位置,多个配置文件时,以逗号分隔一〉
<context-param> 
<param-name>contextConfigLocation<!param-name> 
<!一 Spring 将加载 spring 目录下的 applicationContext .xml 文件一
<param-value> 
classpath:spring/applicationContext.xml 
<!param-value> 
<!context-param> 
<!一指定以 ContextLoaderListener 方式启动 Spring 容器
<listener> 
<listener-class> 
rg.springframework.web.context.ContextLoaderListener
<!listener-class> 
</listener>

获得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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--将指定类配置给 Spring ,让 Spring 创建其对象的实例-->
    <bean id="hello" class="com.example.spring.pojo.Hello">
        <property name="name" value="Spring"/>
    </bean>

</beans>

四、详解 Bean

1、Bean的配置

  • 如果在 bean中未指定id和name,Spring将会将class 值当作 id 使用。
  • 在配置文件中,通常一个普通的 Bean 只需要定义 id (或 name) class 两个属性即可。
  • applicationContext.xml

2、Bean的实例化

在 Spring 中,要想使用容器中的 Bean ,需要实例化 Bean,实例化 Bean 有三种方式,分别为:构造器实例化、静态工厂方式实例化、实例工厂方式实例化(其中最常用的是构造器实例化)。

(1)构造器实例化

构造器实例化是指 Spring 容器通过 Bean 对应类中默认的无参构造方法来实例化 Bean。

    public static void main(String[] args) {
      
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        Hello name = (Hello) context.getBean("hello");
        System.out.println(name);
    }

(2) 静态工厂实例化

使用静态工厂实例化Bean要求开发者创建一个静态工厂的方法来创建 Bean 的实例,其 Bean 配置中的 class 属性所指定的不再是 Bean 实例的实现类,而是静态工厂类,同时还需要使用 factory-method 属性来指定所创建的静态工厂方法。

(3)实例工厂实例化

不再使用静态方法创建 Bean 实例,而是采用直接创建 Bean 实例的方式 同时,在配置文件中,需要实例化的 Bean也不是通过 class 属性直接指向的实例化类,而是通过 factory - bean 属性指向配置的实例工厂,然后使用 factory - method 属性确定使用工厂中的哪个方法。

3、Bean的作用域

bean有七种作用域,常用的是singleton和prototype。Spring 配置文件中, Bean 的作用域是通过<bean> 元素的 scope 属性来指定的,该属性值可以设置为 singleton、prototype、request、session、globalSession、application、websocket七个值。

  • singleton(单例)

使用 singleton 定义的 Bean 在Spring 容器中将只有一个实例,也就是说,无论有多少个 Bean引用它,始终将指向同一个对象,这也是 Spring 容器默认的作用域。

  • prototype(原型)

每次通过 Spring 容器获取的 prototype 定义的 Bean 时,容器都将创建一个新的 Bean 实例。

<bean id="userDao" class="com.example.spring.pojo.UserDao" scope="singleton"/>

4、Bean的生命周期

Spring 容器可以管理 singleton 作用域的 Bean 的生命周期,在此作用域下, Spring 能够精确地知道该Bean 何时被创建,何时初始化完成以及何时被销毁。对于 prototype 作用域的Bean,Spring 只负责创建,当容器创建了 Bean 实例后, Bean 的实例就交给客户端代码来管理,Spring 容器将不再跟踪其生命周期 每次客户端请求 prototype 作用域的 Bean 时, Spring 容器都会创建一个新的实例,并且不会管那些被配置成 prototype 作用域的 Bean 的生命周期。

5、Bean的装配方式/Bean 依赖注入的方式

Bean 的装配可以理解为依赖关系注入Bean 的装配方式即 Bean 依赖注入的方式。Spring 容器支持多种形式的 Bean 的装配方式,如基于 XML 的装配、基于注解( Annotation )的装配、自动装配等。最常用的是基于注解的装配

(1)基于 XML 的装配

Spring 提供了两种基于 XML 的装配方式:设值注入( Setter Injection )和构造注入 (Constructor Injection)。
使用设值注入时,在 Spring 配置文件中,需要使用 <bean> 元素的子元素<property> 来为每个属性注入值;而使用构造注入时,在配置文件里,需要使用 <bean> 元素的子元素<constructor -arg> 来定义构造方法的参数,可以使用其 value 属性(或子元素)来设置该参数的值。
1.1 设值注入

  • Bean 类必须提供一个默认的无参构造方法
  • Bean 类必须为需要注入的属性提供对应的 setter 方法
    <bean id="hello" class="com.example.spring.pojo.Hello" >
        <property name="name" value="Spring"/>
        <property name="list">
            <list>
                <value>"setlistvalue1"</value>
                <value>"setlistvalue2"</value>
            </list>
        </property>
    </bean>

1.2 构造注入

  • Bean提供带所有参数的有参构造方法。
    <bean id="hello" class="com.example.spring.pojo.Hello" >
        <constructor-arg index="0" name="name"/>
        <constructor-arg index="1">
            <list>
                <value>"constructorvalue1"</value>
                <value>"constructorvalue2"</value>
            </list>
        </constructor-arg>
    </bean>

<constructor -arg >元素用于定义构造 参数 其属性 index 表示其索 引从0开始 ,value 属性用于设置注入 值,其子元素<Iist> 来为 User 类中对应的 list集合属性注入值 然后又使用了设值注入方式装 User 类的实 ,其中 <property> 元素用于调bean 实例中的 setter 方法完成属性赋值,从 依赖注入, 其子元素 Ii st> 同样是为 User类中对应 lis 集合属性注入值

(2)基于Annotation(注解)的装配

  1. 使用注解方式一
<context:annotation-config/>

<bean id="myService" class="com.example.spring.service.MyServiceImpl"/>

上述 Spring 配置文件中的注解方式虽然较大程度简化了XML 文件中 Bean 的配置,但仍需要在 Spring 配置文件中一一配置相应的 Bean,比较麻烦。

  1. 使用注解方式二
  • 项目必须要导入spring-aop依赖
  • 配置文件中增加如下内容
<!--使用context命名空间,通知Spring扫描指定包下所有Bean,进行注解解析-->
<context:component-scan base-packaqe="com.example.spring"/>

使用注解装配,在需要配置为bean的类上增加上述Spring注解即可

  • 以下两个是完全等价的
@Service
public class MyServiceImpl {
    
    ...
}

<bean id="myService" class="com.example.spring.service.MyServiceImpl"/>
  1. Spring的注解:

@Component 把这个注解放到类上,这个类被Spring管理了,它就成了一个bean,可以作用在任何层次。`
此注解有三个衍生注解分别用在MVC的三层架构上,但是功能都是一样的,把类注册到Spring中变成bean。

@Controller 用在控制层(Controller)
@Service用在业务层(Service)
@Repository用在数据访问层(DAO)

@Autowired用于对 Bean 的属性变量、属性的 setter 方法及构造方法进行标注,配合对应的注解处理器完成 Bean 的自动配置工作。默认按照 Bean 的类型进行装配。

@Qualifier与@Autowired 注解配合使用,会将默认的按 Bean 类型装配修改为接Bean的实例名称装配, Bean 的实例名称由 @Qualifier 注解的参数指定。

@Resource其作用与 Autowired 一样,其区别在于@Autowired 默认按照 Bean 类型装配,而@Resource 默认按照 Bean 实例名称进行装配 @Resource 中有两个重要属性: name、type,Spring name 属性解析为 Bean 实例名称, type 属性解析为 Bean 实例类型 如果指定 name 属性,则按实例名称进行装配;如果指定 type 属性,则按 Bean 类型进行装配;如果都不指定,则先按 Bean 实例名称装配,如果不能匹配,再按照 Bean 类型进行装自己;如果都无法匹配,则抛出 NoSuchBeanDefinitionException 异常。

(3)自动装配

所谓自动装配,就是将一个 Bean 自动地注入到其他 Bean的Property中。Spring <bean> 元素中包含一个 autowire 属性,我们可以通过设置 autowire 的属性值,autowire=no/byType/byName/constructor,来自动装配 Bean。

  • autowire针对每个bean进行装配:
<bean id="hello" class="com.example.spring.pojo.Hello" autowire="byType"/>
<bean id="hello" class="com.example.spring.pojo.Hello" autowire="byName"/>

byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的bean id
byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean id

五、AOP

1、AOP简介

(1)什么是AOP

AOP 的全称是 Aspect-Oriented Programming ,即面向切面编程(也称面向方面编程)
AOP 用来封装多个类的公共行为,将那些与业务无关,却为业务模块所共同调用的逻辑封装起来,减少系统的重复代码,降低模块间的耦合度。另外,AOP 还解决一些系统层面上的问题,比如日志、事务、权限等。AOP 框架有两个,分别为 Spring AOP、AspectJ。

(2)AOP术语

  • Aspect (切面):切面通常是指封装的用于横向插入系统功能(如事务、曰志等)的类。
  • Joinpoint (连接点):连接点就是指方法的调用
  • Pointcut (切入点):通常指的是类或者方法名,如某个通知要应用到所有以 add开头的方法中,那么所有以 add开头的方法都是切入点。
  • Advice( 通知/增强处理):AOP 框架在特定的切入点执行的增强处理,即在定义好的切入点处所要执行的程序代码。可以将其理解为切面类中的方法,它是切面的具体实现。
  • Target Object (目标对象):是指所有被通知的对象
  • Proxy (代理):将通知应用到目标对象之后,被动态创建的对象
  • Weaving (织入):将切面代码插入到目标对象上,从而生成代理对象的过程

2、动态代理

(1)JDK动态代理

待补充。。。

(2)CGLIB代理

待补充。。。

3、AspectJ

(1)基于XML的声明式AspectJ

待补充。。。

(2)基于注解的声明式AspectJ

待补充。。。

六、Spring JDBC

Spring JDBC 模块负责数据库资源管理,Jdbc T emplate 类是 Spring JDBC 的核心类

1、添加依赖

        <!--spring-jdbc依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.13</version>
        </dependency>
        <!--mysql驱动依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.27</version>
        </dependency>

2、添加JDBC配置

<?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 https://www.springframework.org/schema/context/spring-context.xsd">


    <!-- 1. 读取db.properties文件中的数据 -->
    <context:property-placeholder location="classpath:db.properties"/>

    <!-- 2. 配置数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driverClass}"/>
        <property name="url" value="${jdbc.jdbcUrl}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!-- 3. 配置Spring的jdbcTemplate 并注入dataSource数据源-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置注入类-->
<!--    <bean id="studentService" class="com.example.spring.service.StudentServiceImpl">-->
<!--        <property name="jdbcTemplate" ref="jdbcTemplate"/>-->
<!--    </bean>-->
</beans>

定义 jdbcTemplate 时,需要将 dataSource 注入到 jdbcTemplate 中,而其他需要使用jdbcTemplate的Bean ,也需要将 jdbcTemplate 注入到该 Bean 中(通常注入到 Dao 类中,在Dao 类中进行与数据库的相关操作)。

3、使用Spring JdbcTemplate

    @Test
    public void createTest() {
        // 获取Spring容器
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获得JdbcTemplate实例
        JdbcTemplate jdbcTemplate = (JdbcTemplate) applicationContext.getBean("jdbcTemplate");

        // 创建表
        jdbcTemplate.execute("CREATE TABLE `student` (\n" +
                "  `id` int(11) NOT NULL,\n" +
                "  `name` varchar(255) DEFAULT NULL,\n" +
                "  `age` int(11) DEFAULT NULL,\n" +
                "  PRIMARY KEY (`id`)\n" +
                ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;");
    }

4、dbcTemplate的常用方法

  • 创建Student POJO
  • 创建Student增、删、改、查的Service接口,这里直接创建了类
public class StudentServiceImpl {
    private JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    // 增加
    public int addStudent(Student student) {

        String sql = "insert into student(age,name) values(?,?)";

        // 定义个数组存储sql语句中的参数
        // sql语句里的参数顺序必须和传进去的参数顺序一致
        Object[] obj = new Object[]{

                student.getAge(),
                student.getName()
        };

        int num = this.jdbcTemplate.update(sql, obj);
        return num;
    }

    // 更新

    public int updateStudent(Student student) {
        // sql语句里的参数顺序必须和传进去的参数顺序一致
        String sql = "update student set name=?,age=? where id=?";
        Object[] params = new Object[]{
                student.getName(), student.getAge(), student.getId()
        };

        int num = this.jdbcTemplate.update(sql, params);
        return num;
    }

    // 删除
    public int deleteStudent(int id) {
        String sql = "delete from Student where id = ?";
        int num = this.jdbcTemplate.update(sql, id);
        return num;
    }
    
    // 查询一个
    public Student findStudentById(int id) {
        String sql = "select * from student where id = ?";
        BeanPropertyRowMapper<Student> rowMapper = new BeanPropertyRowMapper<Student>(Student.class);
        return this.jdbcTemplate.queryForObject(sql, rowMapper, id);
    }

    // 查询所有
    public List<Student> findAllStudent() {
        String sql = "select * from student";
        BeanPropertyRowMapper<Student> rowMapper = new BeanPropertyRowMapper<Student>(Student.class);
        return this.jdbcTemplate.query(sql, rowMapper);
    }
}
  • 在appcliationContext.xml里定义一个id为studentService的Bean,用于将jdbcTemplate注入到StudentService实例中。
  • 在单元测试类中测试增、删、改、查。
    @Test
    public void addStudentTest() {
        // 获取Spring容器
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

        StudentServiceImpl studentService = (StudentServiceImpl) applicationContext.getBean("studentService");

        Student student = new Student();

        student.setAge(19);
        student.setName("xie");

        int num = studentService.addStudent(student);

        if (num > 0) {
            System.out.println("成功插入了" + num + "条数据");
        } else {
            System.out.println("插入失败!");
        }
    }

    @Test
    public void updateStudentTest() {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

        StudentServiceImpl studentService = (StudentServiceImpl) applicationContext.getBean("studentService");

        Student student = new Student();
        student.setId(1);
        student.setName("谢");
        student.setAge(28);

        int num = studentService.updateStudent(student);
        System.out.println(num);
    }

    @Test
    public void deleteStudentTest() {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

        StudentServiceImpl studentService = (StudentServiceImpl) applicationContext.getBean("studentService");
        int num = studentService.deleteStudent(1);
        System.out.println(num);
    }

    @Test
    public void findByIdTest() {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

        StudentServiceImpl studentService = (StudentServiceImpl) applicationContext.getBean("studentService");

        Student student = studentService.findStudentById(1);
        System.out.println(student);
    }

    @Test
    public void findAll() {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

        StudentServiceImpl studentService = (StudentServiceImpl) applicationContext.getBean("studentService");

        List<Student> student = studentService.findAllStudent();
        System.out.println(student);
    }

七、Spring 事务

八、Spring工具类

相关文章

网友评论

      本文标题:Spring最佳教学教程入门笔记

      本文链接:https://www.haomeiwen.com/subject/jfdthrtx.html