sping5笔记

1、Spring 入门案例

1.1 、Spring5下载

进入官网https://spring.io/

spring官网

GA表示稳定版

点击GitHub进入

G

点击链接进入

进入

继续进入

a

往下滑找到spring 把导航地址替换

spring

进入后选择相应的版本下载

a

1.2 入门案例

1.首先导入5个jar包

导包

2、创建普通类,在这个类中添加普通方法

package com.spring5;

/**
 * @author JLLStart
 * 2022/10/10 20:00
 */
public class User {
    public void add(){
        System.out.println("add...");
    }
}

3、创建Spring配置文件,在配置文件配置创建的对象

(1)Spring配置文件使用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">    

    <!--  配置User对象创建  -->
    <bean id="user" class="com.spring5.User"></bean>
</beans>

4、进行测试代码编写

package com.spring5.TestDemo;

import com.spring5.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author JLLStart
 * 2022/10/10 20:12
 */
public class TestSpring5 {
    @Test
    public void testAdd(){
        //1 加载Spring配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");

        //2.获取配置创建的对象
        User user = context.getBean("user", User.class);

        System.out.println(user);
        user.add();
    }
}

2、IOC-控制反转

2.1、IOC是什么

(1) 控制 反 转 把 对 象 创建 和 对 象 之 间 的 调用 过 程 ,交 给 Spring 进行 管理 。
(2) 使 用 IOC 目的 : 为了耦合 度 降 低 。
(3) 做 入 门 案例 就 是 IOC 实现

2.2、IOC底层原理

​ (1) xml 解 析

XML解析

(2) 工厂模式

工厂模式解耦

(3) 反 射

2.3、IOC容器实现的两种方式(两个接口)

(1) BeanFactoty

​ IOC容器基本实现,是Spring加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象。内部的使用接口,不提供开发人员进行使用。加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象。

(2) ApplicationContext:

​ BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用。

ApplicationContext有两个实现接口:

接口

2.4、 IOC操作Bean管理(基于xml配置文件方式实现)

2.4.1、什么是Bean管理

  1. Spring 创建对象
  2. Spring注入属性

2.4.2、Bean管理操作有两种方式

1、基于xml配置文件方式实现

​ 1.1、Spring创建对象:

<!--  配置User对象创建  -->
<bean id="user" class="com.spring5.User"></bean>


(1)在spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建
(2)在bean标签有很多属性,介绍常用的属性。
        *   id属性:唯一标识。
        *   class属性:类全路径(包类路径)。
(3)创建对象时候,默认也是执行无参数构造方法完成对象创建。
  1. 2、Spring注入属性

    1.2.1、使用set方法注入

<!-- set方法注入属性 -->
<bean id="book" class="com.spring5.Book">
    <!-- 使用property完成属性注入
            name: 类里面厲性名称
            value:向属性注入的值
        -->
    <property name="name" value="易筋经"/>
</bean>


<!-- XML注入其他类型属性-->
<!-- 1.null值-->
    <!-- 设置空值null -->
    <property name="name">
        <null/>
    </property>

<!--2.属性值包含特殊符号-->
        <!-- 属性值包含特殊符号
            1. 把 <> 进行转义  -> &lt;&gt;
            2. 把带特殊符号内容写入CDATA
         -->
        <property name="address">
            <!-- <![CDATA[此处填属性值]> -->
            <value><![CDATA[<南京>]]></value>
        </property>

p名称空间注入(应用于set方法 了解就行)

 <!-- 首先要添加名称空间 -->
xmlns:p="http://www.springframework.org/schema/p"



<bean id="book2" class="com.spring5.Book" p:name="吸星大法" p:author="任我行"/>

​ 1.2.2、使用有参数构造注入

    <!-- 3.有参数构造注入属性 -->
    <bean id="order" class="com.spring5.Order">
<!--        <constructor-arg index="0" value="郭靖"/>-->
<!--        <constructor-arg index="1" value="襄阳"/>-->
        <constructor-arg name="name" value="郭靖"/>
        <constructor-arg name="address" value="襄阳"/>

    </bean>

注意:

注入普通属性需要注意的点使用 set 方法注入属性的时候,即在bean 标签内部使用 property 标签进行属性注入要创建对应的 set 方法,然后配置 xml 文件才有效,否则会报错

**同理,使用有参构造器设置属性的时候,即在 bean 标签内部使用constructor-arg标签进行属性注入,要求类中有对应参数的构造器 **

2、基于注解方式实现。

2.4.3 、注入外部bean

ref属性:外部bean的id值
通过ref属性将外部bean注入

UserService实现类

package com.spring5.service;

import com.spring5.dao.UserDao;
import com.spring5.dao.UserDaoImpl;

/**
 * @author JLLStart
 * 2022/10/11 18:18
 */
public class UserServiceImpl implements UserService {

    private UserDao userDao;

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


    @Override
    public void service() {
        userDao.add();
    }
}

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

    <!-- service 和 dao 对象创建-->
    <bean id="userService" class="com.spring5.service.UserServiceImpl">
        <!-- 注入UserDao对象 -->
        <property name="userDao" ref="userDaoImpl"/>
    </bean>

    <bean id="userDaoImpl" class="com.spring5.dao.UserDaoImpl">
		
    </bean>
</beans>

2.4.4 、注入内部bean

嵌套bean

    <bean id="employ" class="com.spring5.bean.Employ">
        <property name="name" value="岳不群"/>
        <property name="gender" value=""/>
        <!-- 设置对象类型属性 -->
        <property name="dep">
            <bean id="department" class="com.spring5.bean.Department">
                <property name="name" value="安保部"/>
            </bean>
        </property>
    </bean>

2.4.5、注入属性-级联赋值

    <!-- 级联赋值 -->
    <bean id="employ" class="com.spring5.bean.Employ">
        <property name="name" value="岳不群"/>
        <property name="gender" value=""/>
        <!-- 级联赋值 -->
        <property name="dep" ref="dept"/>
        <property name="dep.name" value="技术部"/>
    </bean>

    <bean id="dept" class="com.spring5.bean.Department">
        <property name="name" value="财务部"/>
    </bean>xl

注意:这里使用dep.name 需要在Employ类写getDep()方法 否则报错

2.4.6、XML注入集合属性

1、注入数组类型属性

<!-- 数组属性注入 -->
        <property name="courses">
            <array>
                <value>Java</value>
                <value>Python</value>
                <value>数据库</value>
            </array>
        </property>

2、注入list类型属性

        <!-- list类型属性注入 -->
        <property name="list">
            <list>
                <value>东方不败</value>
                <value>令狐冲</value>
                <value>田伯光</value>
            </list>
        </property>

3、注入map类型属性

        <!-- map类型属性注入 -->
        <property name="map">
            <map>
                <entry key="JAVA" value="java"/>
                <entry key="PHP" value="php"/>
                <entry key="PYTHON" value="python"/>
            </map>
        </property>

4、注入set类型属性

        <!-- set属性注入 -->
        <property name="set">
            <set>
                <value>MySql</value>
                <value>Oracle</value>
            </set>
        </property>

**提取集合注入部分: **

(1)在spring配置文件引入名称空间util

util

(2)使用util标签完成list集合注入提取

    <!-- 1.提取list集合属性注入 -->
    <util:list id="bookList">
        <value>易筋经</value>
        <value>九阴真经</value>
        <value>吸星大法</value>
    </util:list>

    <!-- 2.注入使用 -->
    <bean id="book" class="com.spring5.collectionType.Book">
        <property name="list" ref="bookList"/>
    </bean>

2.4.7、FactoryBean

FactoryBean

2.4.8、bean作用域

在spring配置文件bean标签里面有属性**scope** 用于设置单实例还是多实例。

  • singleton:单例,默认也是这个,加载spring配置文件时候就会创建单实例对象
  • prototype:多例,在调用getBean方法时候创建多实例对象
<!-- 2.注入使用 -->
    <bean id="book" class="com.spring5.collectionType.Book" scope="prototype">
        <property name="list" ref="bookList"/>
    </bean>

2.4.9、bean的生命周期

基本声明周期

​ (1) 通过构造器创建bean实例 (无参数构造)。
​ (2) 为bean的属性设置值和对其他bean引用 (调用set方法)
​ (3) 调用bean的初始化的方法 (需要进行配置初始化的方法 )
​ (4) bean可以使用了 (对象获取到了)
​ (5) 当容器关闭时候,调用bean的销毁的方法 ( 需要进行配置销毁的方法)

加上后置处理器的生命周期

(1)  通过构造器创建bean实例        (无参数构造)。
(2)  为bean的属性设置值和对其他bean引用         (调用set方法)
(3) 把bean实例传递bean后置处理器的方法postProcessAfterInitialization.
(4) 调用bean的初始化的方法           (需要进行配置初始化的方法 )  
(5) 把bean实例传递bean后置处理器的方法postProcessAfterInitialization.
(6)  bean可以使用了        (对象获取到了) 
(7) 当容器关闭时候,调用bean的销毁的方法      ( 需要进行配置销毁的方法)

后置处理器

package com.spring5.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * @author JLLStart
 * 2022/10/14 10:56
 */
public class BeanPost implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化之前");
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化之后");
        return null;
    }
}

**注意:**在配置文件中配置了后置处理器,对当前配置文件中所有的bean都有效

2.4.10、XML自动装配

自动装配含义:
根据指定装配规则(属性名称或者属性类型),Spring 自动将匹配的属性值进行注入

<!-- 根据名称自动注入 -->
    <bean id="employ" class="com.spring5.autowire.Employ" autowire="byName">
<!--        <property name="department" ref="department"/>  -->
    </bean>

        <!-- 根据类型自动注入 -->
    <bean id="employ" class="com.spring5.autowire.Employ" autowire="byType">
<!--        <property name="department" ref="department"/>  -->
    </bean>


    <bean id="department" class="com.spring5.autowire.Department">

    </bean>

2.4.11、外部属性文件

1.演示数据库连接配置:

# 数据库驱动
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
# 数据库连接
jdbc.url=jdbc:mysql://localhost:3306/test2?serverTimezone=UTC
# 数据库用户名
jdbc.username=root
# 数据库密码
jdbc.password=root
#最大连接数
jdbc.maxActive=300
#初始化连接数
jdbc.initialSize=2
#获取连接最大等待时间
jdbc.maxWait=60000
#最小连接数
jdbc.minIdle=1
#检测连接有效性的时间间隔
jdbc.timeBetweenEvictionRunsMillis=60000
#连接保持空闲而不被驱逐的最长时间
jdbc.minEvictableIdleTimeMillis=300000
#连接有效性,检测sql
jdbc.validationQuery=SELECT 'x'
#定时检测空闲连接有效性
jdbc.testWhileIdle=true
#检测获取的连接的有效性
jdbc.testOnBorrow=false
#检测要归还的连接的有效性
jdbc.testOnReturn=false
#是否缓存preparedStatement,即PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
jdbc.poolPreparedStatements=false
jdbc.maxOpenPreparedStatements=50

2.把外部properties属性文件引入到Spring配置文件中

​ 引入context名称空间

    <!-- 引入外部属性文件 -->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!-- 配置数据库信息 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${jdbc.url}"/>
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>

2.5、IOC操作Bean管理(基于注解)

2.5.1、Spring针对Bean管理中创建对象提供注解

(1) @Component (普通注解创建对象)
(2) @Service (一般在业务逻辑层)
(3) @Controller (一般在Web层)
(4) @Repository (一般在DAO层)

这四个注解功能是一样的,都可以用来创建bean实例,为了区分 建议遵守规范

2.5.2、基于注解方式实现对象创建

1.引入依赖

2.开启组件扫描

这里也要引入名称空间context

<!--开启组件扫描
    1如果扫描多个包,多个包使用逗号隔开
    2扫描包上层目录(推荐)
-->
    <context:component-scan base-package="com.spring5.dao,com.spring5.service">
        
    </context:component-scan>

3.第三步创建类,在类上面添加创建对象注解。

4.开启组件扫描细节配置

    <!-- 示例1
        use - -default-filters=' false" 表示现在不使用默认filter,自己配置filter
        context:include-filter,设置扫描哪些内容

     -->
    <context:component-scan base-package="com.spring5" use-default-filters="false">
        <!-- 过滤包含Component注解的类 -->
        <context:include-filter type="annotation"
                                expression="org.springframework.stereotype.Component"/>
    </context:component-scan>

    <!-- 示例2
        use - -default-filters=' false" 表示现在不使用默认filter,自己配置filter
        context:exclude-filter,设置不扫描哪些内容

     -->
    <context:component-scan base-package="com.spring5" use-default-filters="false">
        <!-- 过滤不包含Component注解的类 -->
        <context:exclude-filter type="annotation"
                                expression="org.springframework.stereotype.Component"/>
    </context:component-scan>

2.5.3、属性注入

(1) @Autowired: 根据属性类型进行自动装配
(2) @Qualifier: 根据属性名称进行注入。
(3) @Resource: 可以根据类型注入,可以根据名称注入
(4) @Value: 注入普通类型属性

Dao层

@Repository
public class AnnotationDaoImpl implements AnnotationDao {
    @Override
    public void add() {
        System.out.println("dao...add");
    }
}

Service层

@Service
public class AnnotationService {

    //定义dao类型属性
    //不需要添加set方法
    //添加注入属性注解
    @Autowired  // 根据类型自动注入
    private AnnotationDao annotationDao;

    public void add() {
        System.out.println("add ...");
        annotationDao.add();
    }
}

注意:

  • 使用@Autowired 注解进行属性注入不需要添加 set 方法
  • 单独使用@Autowired 注解,只能有一个实现类,多个实现类会报错;
  • @Qualifier 必须与@Autowired 一起使用,唯一的确定某类型某实现类的属性;

@Value注解

2.5.4、完全注解开发

(1) 创建配置类,替代xml配置文件。

@Configuration //作为配置类,替代xml配置文件
@ComponentScan(basePackages = {"com.spring5"})
public class SpringConfig {

}

(2) 编写测试类

// 完全注解开发
@Test
public void testService2() {
    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    AnnotationService annotationService = context.getBean("annotationService", AnnotationService.class);
    annotationService.add();
    System.out.println(annotationService);
}

3、AOP-面向切面编程

3.1 AOP是什么

(1)面向切面编程,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用 性,同时提高了开发的效率。
(2)通俗描述:不通过修改源代码方式,在主干功能里面添加新功能

3.2、AOP底层原理

1、AOP底层使用动态代理

有两种情况动态代理:

  • 有接口情况,使用JDK动态代理。创建接口实现类代理对象,增强类的方法
  • 没有接口情况,使用CGLIB动态代理。

3.3、JDK动态代理(有接口)

(1) 创建接口,定义方法。

public interface UserDao {
    public int add(int a, int b);

    public String update(String id);
}

(2)创建接口实现类,实现方法

public class UserDaoImpl implements UserDao {

    @Override
    public int add(int a, int b) {
        return a + b;
    }

    @Override
    public String update(String id) {
        return id;
    }
}

(3) 使用Proxy类创建接口代理对象

package com.spring5.AOP.proxy;

import com.spring5.AOP.dao.UserDao;
import com.spring5.AOP.dao.UserDaoImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author JLLStart
 * 2022/10/15 14:30
 */
public class JdkProxy {
    public static void main(String[] args) {
        //创建接口实现类代理对象

        Class[] interfaces = {UserDao.class};
//        Proxy.newProxyInstance(JdkProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
//            @Override
//            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                return null;
//            }
//        });
        UserDaoImpl userDao = new UserDaoImpl();
        UserDao proxyInstance = (UserDao) Proxy.newProxyInstance(JdkProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
        System.out.println(proxyInstance.add(1, 39));
    }
}

// 创建代理对象代码
class UserDaoProxy implements InvocationHandler {

    // 传递被代理类
    private Object obj;

    public UserDaoProxy(Object obj) {
        this.obj = obj;
    }

    // 增强的逻辑
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object res = method.invoke(obj, args);
        return res;
    }
}

3.4、AOP操作术语

3.5、AOP操作

3.5.1、准备工作

1、Spring 框架-般都是基于Aspect]实现AOP操作s
(1)什么是AspectJ:
AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用,进
行AOP操作。
2、基于AspectJ实现AOP操作s
(1)基于xml配置文件实现
(2)基于注解方式实现(使用)

3、引入AspectJ依赖

        <!-- https://mvnrepository.com/artifact/net.sourceforge.cglib/com.springsource.net.sf.cglib -->
        <dependency>
            <groupId>net.sourceforge.cglib</groupId>
            <artifactId>com.springsource.net.sf.cglib</artifactId>
            <version>2.2.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.9.1</version>
            <scope>runtime</scope>
        </dependency>

4、切入点表达式
(1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强、

(2)语法结构:。
execution([权限修饰符][返回类型] [类全路径] [方法名称]([参数列表]) )
举例1:对com.atguigu.dao.BookDao类里面的add进行增强。
execution(* com.atguigu.dao.Book.add(…))

举例2:对com.atguigu.dao. BookDao类里面的所有的方法进行增强
execution(*com.atguigu.dao.BookDa.* (…))

举例3:对com.atguigu.dao包里面所有类,类里面所有方法进行增强.
execution(* com.atquiqu.dao.*.* (… )

3.5.2、AspectJ注解

1、创建类,在类里面定义方法

public class User {
    public void add(){
        System.out.println("add...");
    }
}

2、创建增强类(编写增强逻辑)

(1)在增强类里面,创建方法,让不同方法代表不同通知类型.

public class UserProxy {

    // 前置通知
    public void before(){
        System.out.println("before...");
    }
}

3、进行通知的配置
(1)在spring配置文件中,开启注解扫描

<?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">

    <context:component-scan base-package="com.spring5.AOP">

    </context:component-scan>
</beans>

​ (2)使用注解创建User和UserProxy对象

​ 在这两个类中添加注解@Component

​ (3) 在增强类上面添加注解@Aspects

​ (4)在spring配置文件中开启生成代理对象

<!--    开启Aspect生成代理对象-->
    <aop:aspectj-autoproxy>
        
    </aop:aspectj-autoproxy>

4、配置不同类型的通知

package com.spring5.AOP.proxy;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @author JLLStart
 * 2022/10/15 23:07
 */
@Component
@Aspect // 生成代理对象
public class UserProxy {

    // 前置通知
    //@Before注解表示作为前置通知
    @Before(value = "execution(* com.spring5.AOP.AspectJ.User.add(..))")
    public void before() {
        System.out.println("before...");
    }

    // 最终通知
    @After(value = "execution(* com.spring5.AOP.AspectJ.User.add(..))")
    public void after() {
        System.out.println("after...");
    }

    // 后置通知
    @AfterReturning(value = "execution(* com.spring5.AOP.AspectJ.User.add(..))")
    public void afterReturning() {
        System.out.println("afterReturning...");
    }

    // 异常通知
    @AfterThrowing(value = "execution(* com.spring5.AOP.AspectJ.User.add(..))")
    public void afterThrowing() {
        System.out.println("afterThrowing...");
    }

    // 环绕通知
    @Around(value = "execution(* com.spring5.AOP.AspectJ.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) {
        System.out.println("环绕之前");

        try {
            proceedingJoinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }

        System.out.println("环绕之后");
    }
}

5、相同切入点抽取

// 相同切入点抽取
@Pointcut(value = "execution(* com.spring5.AOP.AspectJ.User.add(..))")
public void point(){
	
}

// 前置通知
//@Before注解表示作为前置通知
@Before(value = "point()")
public void before() {
    System.out.println("before...");
}

6、有多个增强类多同-一个方法进行增强,设置增强类优先级
(1)在增强类上面添加注解@Order(数字类型值),数字类型值越小优先级越高。

@Component
@Aspect
@Order(2)
public class UserProxy2 {
    @Before(value = "execution(* com.spring5.AOP.AspectJ.User.add(..))")
    public void before2() {
        System.out.println("before2...");
    }
}

7、完全注解开发

@Configuration //标注为配置类
@ComponentScan(basePackages = {"com.spring5.AOP"})  //开启注解扫描
@EnableAspectJAutoProxy(proxyTargetClass = true)    //开启Aspect自动生成代理对象
public class ConfigAop {
}

3.5.3、AspectJ配置文件

1、创建两个类,增强类和被增强类,创建方法
2、在spring配置文件中创建两个类对象

<!-- 创建对象 -->
<bean id="book" class="com.spring5.AOP.aopxml.Book"/>

<bean id="bookProxy" class="com.spring5.AOP.proxy.BookProxy"/>

3、在spring配置文件中配置切入点

<!-- 配置aop增强-->
    <aop:config>
    <!--   切入点-->
        <aop:pointcut id="p" expression="execution(* com.spring5.AOP.aopxml.Book.buy(..))"/>

    <!--  配置切面-->
        <aop:aspect ref="bookProxy">
            <aop:before method="before" pointcut-ref="p"/>
        </aop:aspect>
    </aop:config>

4、JDBCTemplate

4.1、JdbcTemplatev概念和准备工作

概念:Spring 框架对JDBC进行封装,使用JdbcTemplate方便实现对数据库操作

准备工作:

1、引入依赖

<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.8</version>
</dependency>

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.30</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.23</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.3.23</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
 <!-- 用来整合其他框架 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>5.3.23</version>
</dependency>

2、配置数据库连接池

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="url" value="jdbc:mysql://localhost:3306/springUser?serverTimeZone=UTC"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
</bean>

3、配置JDBCTemplate对象,注入DataSource

<bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <!-- 注入DataSource -->
    <property name="dataSource" ref="dataSource"/>
</bean>

4、创建service类, 创建dao类,在dao注入jdbcTemplate对象

  • 组件扫描:
<context:component-scan base-package="com.spring5.JDBCTemplate"/>
  • service
package com.spring5.JDBCTemplate.service;

import com.spring5.JDBCTemplate.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author JLLStart
 * 2022/10/16 16:50
 */
@Service
public class BookService {
    // 注入Dao
    @Autowired
    private BookDao bookDao;
}

4.2、操作数据库

4.2.1、增删改查

  • 增删改
@Repository
public class BookDaoImpl implements BookDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void add(Book book) {
        //1.创建sql语句
        String sql = "insert into t_book values(?,?,?)";
        //2.调用 方法
        int update = jdbcTemplate.update(sql, book.getUserId(), book.getUsername(), book.getUstatus());
        System.out.println(update);
    }
}
  • 查询返回某个值
//查询表中记录数
@Override
public int selectCount() {
    String sql = "select count(*) from t_book";
    return jdbcTemplate.queryForObject(sql, Integer.class);
}
  • 查询返回对象

**这里的Book类需要有无参构造器 **

@Override
public Book findBookInfo(String id) {
    String sql = "select * from t_book where user_id = ?";
    return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Book.class), id);
}
  • 查询返回集合
// 查询返回集合对象
@Override
public List<Book> findAllBook() {
    String sql = "select * from t_book";
    return jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(Book.class));
}

4.2.2、批量操作数据

DAO实现类

@Override
public void addBooks(List<Object[]> bookList) {
    String sql = "insert into t_book values(?,?,?)";
    int[] ints = jdbcTemplate.batchUpdate(sql, bookList);
    System.out.println(Arrays.toString(ints));
}

测试

@Test
public void testBookService5() {
    ApplicationContext context = new ClassPathXmlApplicationContext("JDBCTemplate/bean1.xml");
    BookService bookService = context.getBean("bookService", BookService.class);
    List<Object[]> books = new ArrayList<>();
    Object[] o1 = {"3", "c++","a"};
    Object[] o2 = {"4", "Rust","r"};
    Object[] o3 = {"5", "Ruby","R"};
    Collections.addAll(books,o1,o2,o3);
    bookService.batchAdd(books);
}

4.3、事务管理

spring提供-一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类

4.3.1、声明式事务管理(注解操作)

1、在spring配置文件配置事务管理器

<!-- 创建事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!-- 注入数据源 -->
    <property name="dataSource" ref="dataSource"/>
</bean>

2、在spring配置文件,开启事务注解

(1)引入tx名称空间

(2)开启事务注解

<tx:annotation-driven transaction-manager="transactionManager"/>

3、在service类上面(获取service类里面方法上面)添加事务注解

(1) @Transactional, 这个注解添加到类上面,也可以添加方法上面。
(2)如果把这个注解添加类上面,这个类里面所有的方法都添加事务
(3)如果把这个注解添加方法上面,为这个方法添加事务,

声明式事务管理参数配置

1、propagation:事务传播行为

2、ioslation: 事务隔离级别。
(1)事务有特性成为隔离性,多事务操作之间不会产生影响, 不考虑隔离性产生很多问题。
(2)有三个读问题:脏读、不可重复读、虚(幻)读
(3)脏读:一个未提交事务读取到另-一个未提交事务的数据
(4)一个未提交事务读取到另-提交事务修改数据
(5)一个未提交事务读取到另一提交事务添加数据

​ 解决读问题:

3、timeout: 超时时间。

​ (1) 事务需要在一定时间内进行提交,如果不提交进行回滚。
​ (2)默认值是-1,设置时间以秒单位进行计算

4、readOnly: 是否只读

​ (1)读:查询操作,写:添加修改删除操作。
​ (2) readOnly 默认值false,表示可以查询,可以添加修改删除操作。
​ (3)设置readOnly,值是true, 设置成true之后,只能查询。

5、rollbackFor: 回滚。

​ 设置出现哪些异常进行事务回滚

6、noRollbackFor: 不回滚

​ 设置出现哪些异常不进行事务回滚

4.3.2、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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx.xsd">

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="jdbc:mysql://localhost:3306/springuser?serverTimeZone=UTC"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    </bean>

    <bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!-- 注入DataSource -->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <context:component-scan base-package="com.spring5.JDBCTemplate"/>

    <!-- 创建事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 注入数据源 -->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--2配置通知-->
    <tx:advice id="txadvice" >
        <!--配置事务参数-->
        <tx:attributes>
            <!--指定哪种规则的方法_上面添加事务-->
            <tx:method name="accountMoney" propagation="REQUIRED"/>
            <!--<tx:method name= "account*'” />-->
         </tx:attributes>
    </tx:advice>
        <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="pt" expression=" execution(* com.spring5.JDBCTemplate.service.*(..))"/>
        <!--配置切面-->
        <aop:advisor advice-ref="txadvice" pointcut-ref="pt" />
    </aop:config>
</beans>

4.3.3、完全注解生命式事务管理

package com.spring5.JDBCTemplate.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

/**
 * @author JLLStart
 * 2022/10/18 21:30
 */
@Configuration
@ComponentScan(basePackages = {"com.spring5.JDBCTemplate"})
@EnableTransactionManagement() // 开启事务注解
public class TxConfig {

    // 创建数据库连接池
    @Bean
    public DruidDataSource getDruidDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/springuser?serverTimeZone=UTC");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        return dataSource;
    }

    // 创建JdbcTemplate对象
    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);  // IOC容器根据类型自动注入
        return jdbcTemplate;
    }

    // 创建事务管理器
    @Bean
    public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }
}

5、spring5新功能

5.1、整合日志框架

1、整个Spring5框架的代码基于Java8, 运行时兼容JDK9, 许多不建议使用的类和方法
在代码库中删除。
2、Spring5.0框架自带了通用的日志封装
(1) Spring5 已经移除Log4jConfigListener, 官方建议使用Log4j2
(2) Spring5 框架整合Log4j2

​ 导入依赖

<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.19.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.19.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.0.3</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.19.0</version>
</dependency>

5.2、支持@Nullable注解

@Nullable 注解可以使用在方法上面,属性上面,参数上面,表示方法返回可以为空,属性值可以
为空叁数值可以 为空,

5.3、Spring5核心容器支持函数式风格GenericApplicationContext

5.4、Spring5 支持整合JUnit5

(1)整合JUnit4
第一步 引入Spring相关针对测试依赖。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.3.23</version>
    <scope>test</scope>
</dependency>

第二步 创建测试类,使用注解方式完成

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:JDBCTemplate/bean2.xml")
public class JTest4 {
    @Autowired
    private UserService userService;

    @Test
    public void testJunit4(){
        userService.accountMoney();
    }
}

(2)整合JUnit5

使用复合注解

package com.spring5.newAbility.service;


import com.spring5.JDBCTemplate.service.UserService;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

/**
 * @author JLLStart
 * 2022/10/19 13:27
 */
@SpringJUnitConfig(locations = "classpath:JDBCTemplate/bean2.xml")
public class JTest5 {
    @Autowired
    private UserService userService;

    @Test
    public void testJunit4(){
        userService.accountMoney();
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值