Spring最佳教学教程入门笔记

2022-01-15  本文已影响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 的编程。


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

二、体系架构

image.pngimage.png

1、核心容器

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

2、数据访问/集成

3、web层

4、其它模块

进行分离,以降低搞合性

面编程 (AOP) 框架

二、快如搭建

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的配置

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

每次通过 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 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 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. 使用注解方式二
<!--使用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。

<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术语

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的常用方法

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);
    }
}
    @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工具类

上一篇 下一篇

猜你喜欢

热点阅读