Spring

目录

1.Spring 5简单介绍

1、spring是轻量级的开源的JavaEE框架

2.、Spring可以解决企业应用开发的复杂性

3、Spring有俩个核心部分:IOC和AOP

​ (1)IOC:控制反转,把创建对象过程交给Spring进行管理

​ (2)AOP:面向切面,不修改源代码进行功能增强

4、Spring特点

(1)方便解耦,简化开发

(2)AOP编程支持

(3)方便Junit测试

(4)方便和其他框架进行整合

(5)方便进行事务操作

(6)降低API开发难度

2.IOC(反转控制)

1.什么是IOC

(1)控制反转,把对象的创建和对象之间调用的过程,交给Spring进行管理

​ (2)使用IOC目的:为了降低耦合度

​ Spring 核心容器(Core)提供Spring框架的基本功能。核心容器的主要组件是BeanFactory,它是工厂模式的实现。BeanFactory使用控制反转(Ioc)模式将应用程序的配置和依赖性规范与实际的应用代码程序分开。Spring的声明式事务基于AOP实现,却并不需要程序开发者成为AOP专家,亦可轻易使用Spring的声明式事务管理。

2.IOC底层原理

​ (1)xml解析、工厂模式、反射

image-20211029164255101

image-20211029164501166

​ (2)IOC过程:

​ 降低耦合度:如当Dao路径发生改变时,只需要修改xml配置文件中的 class属性就可以image-20211029165314622

(3)IOC(接口)

​ 1.IOC思想基于IOC容器完成,IOC容器底层就是对象工厂(如上图)

​ 2.Spring提供IOC容器俩种实现方式:(两个接口)

​ 1、 BeanFactory:IOC容器基本实现,时Spring内部的使用接口。

​ *加载配置文件时不会创建对象,在获取和使用时才会创建对象

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

​ 加载配置文件时,就会创建对象。

	ApplicationContext的实现类有两个:

​ ①FileSystemXmlApplicationContext

​ ②ClassPathXmlApplicationContext

(4)IOC操作 Bean管理

​ 1、什么时Bean管理

​ ①Spring创建对象

​ ②Spring注入属性

3.Bean管理操作的两种方式

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

(1)注入对象

  
<bean id="user" class="com.wanghao.Sping5_demo1.User"></bean>
        //在Spring 配置文件中,使用bean标签,标签里面添加对应的属性,实现对象创建
        //在bean标签有很多常用的属性:
			id: 给对象取一个标示,通过该参数可以获取到对象
			class: 类的全路径
			name: 与id效果相同,但id中无法加特殊符号,name则可以
        //创建对象时,默认也执行无参的构造方法

(2)注入属性

​ DI:依赖注入,注入属性,需要在创建对象的基础之上完成

​ ①:通过set方法实现属性注入 注意:要注入属性一定要在类中声明属性的set方法

<bean id="book" class="com.wanghao.Sping5_demo1.Book">
        <!--使用property完成属性注入
            name 表示属性名称
            value 属性值
        -->
        <property name="bookName" value="三体"></property>
        <property name="bookId" value="123"></property>
    </bean>  
    
    @Test
    public void testbook1()
    {
        ApplicationContext context = new ClassPathXmlApplicationContext ("bean1.xml");
        Book book = context.getBean ("book",Book.class);
        System.out.println (book.getBookName ());
    }

        

​ ②:通过含参构造方法注入属性

 <!--有参构造方法注入属性
        index : 表示构造方法中的第几个参数 0 就是第一个 1...
    -->
    <bean id="orders" class="com.wanghao.Sping5_demo1.Orders">
        <constructor-arg name="orderId" value="123"></constructor-arg>
        <constructor-arg name="orderName" value="护肤品"></constructor-arg>
    </bean>

​ ③:p名称注入

修改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">
进行注入 
<bean id="orders" class="com.wanghao.Sping5_demo1.Orders" p:oderName="护肤品" 
    p:orderId="123"></bean>

若要将属性值设为null

<property name="address" >
	<null/>
</property>

若属性值中有特殊符号

   <!--若属性值带有特殊符号
            1、把特殊符号进行转义 &lt; &gt;
            2、把带特殊符号内容进行CDATA
        -->
        <property name="address">
            <value><![CDATA[<<好家伙>>]]></value>
        </property>
注入属性-外部bean

​ 创建两个类,service 和 dao,在service中调用dao中声明的方法,然后在spring中配置

    <!--service和dao对象的创建-->
    <bean id="userService" class="com.wanghao.service.UserService">
        <!--注入dao对象
               name:类里面的属性名称
               ref:创建的UserDao对象bean标签的id值U
        -->
        <property name="userDao" ref="userDao"></property>
    </bean>
    <bean id="userDao" class="com.wanghao.dao.impl.UserDaoimpl"></bean>
        
     @Test
    public void testAdd()
    {
        ApplicationContext context = new ClassPathXmlApplicationContext ("bean2.xml");
        UserService userService = context.getBean ("userService",UserService.class);
        userService.testadd ();
    }

注入属性-内部bean和级联赋值

(1)一对多关系:部门和员工;

(2)在实体类中表示一对多关系

内部bean:

 <!--
        内部bean 在emp bean内部再声明一个dept bean
    -->
    <bean id="emp" class="com.wanghao.bean.Emp">
        <!--设置普通属性-->
        <property name="ename" value="wanghao"></property>
        <property name="gender" value="女"></property>
        <!--设置对象类型的属性-->
        <property name="dept">
            <bean id="deptm" class="com.wanghao.bean.Dept">
                <property name="dName" value="财政部"></property>
            </bean>
        </property>
    </bean>

级联赋值:

<bean id="emp" class="com.wanghao.bean.Emp">
        <!--设置普通属性-->
        <property name="ename" value="wanghao"></property>
        <property name="gender" value="女"></property>
    	<property name="dept" value="deptm"></property>
</bean>
<bean id="deptm" class="com.wanghao.bean.Dept">
    <property name="dname" value="财务部"></property>
</bean>
注入集合类型的属性

​ ①注入数组类型属性

​ ②注入List集合类型属性

​ ③注入Map集合类型属性

 <bean id="stu" class="com.Spring5_demo2.collectiontype.Stu">
        <!--数组类型的属性注入-->
            <property name="course">
                <array>
                    <value>java</value>
                    <value>oracle</value>
                    <value>linux</value>
                </array>
            </property>

            <property name="list">
                <list>
                    <value>张三</value>
                    <value>里斯</value>
                    <value>王二</value>
                </list>
            </property>

            <property name="maps">
                <map>
                    <entry key="1" value="北京"></entry>
                    <entry key="2" value="上海"></entry>
                    <entry key="3" value="广州"></entry>
                </map>
            </property>
            <property name="set">
                <set>
                    <value></value>
                </set>
            </property>
    </bean>

④注入对象集合

 <!--注入list集合类型 集合中存放的是对象-->
        <property name="listcourse">
            <list>
                <ref bean="curse1"></ref>
                <ref bean="curse2"></ref>
                <ref bean="curse3"></ref>
            </list>
        </property>
    </bean>
<bean id="curse1" class="com.Spring5_demo2.collectiontype.Curse">
    <property name="curseName" value="计算机组成原理"></property>
</bean>
<bean id="curse2" class="com.Spring5_demo2.collectiontype.Curse">
    <property name="curseName" value="Linux高级编程"></property>
</bean>
<bean id="curse3" class="com.Spring5_demo2.collectiontype.Curse">
    <property name="curseName" value="计算机网络"></property>
</bean>
将集合注入部分提取出来

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

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

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

  <!--提取集合类型注入-->
    <util:list id="booklist">
        <value>java</value>
        <value>c++</value>
        <value>python</value>
    </util:list>

   <bean id="book" class="com.Spring5_demo2.collectiontype.Book">
        <property name="list" ref="booklist"></property>
   </bean>

IOC操作Bean

IOC操作Bean管理(FactoryBean)

​ 1.Spring中有两种bean,一种普通bean,一种工厂bean

​ 2.普通bean:在xml配置文件中定义的类型就是返回类型

​ 3.工厂bean:在xml配置文件中定义的类型可以与返回类型不一样

​ ①创建一个类,让这个类作为工厂bean,实现接口FactoryBean

​ ②实现接口里面的方法,在实现的方法中定义返回的bean类型

//XML/factory.xml
<bean id="Mybean" class="com.Spring5_demo2.factoryBean.Mybean">
</bean>
   
//package com.Spring5_demo2.factoryBean; 
public class Mybean implements FactoryBean<Curse>{

    @Override
    public Curse getObject() throws Exception {
        Curse curse = new Curse ();
        curse.setCurseName ("Spring5");
        return curse;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

//package com.Spring5_demo2.Test;
  @Test
    public void Mybeantest()
    {
        ApplicationContext context = new ClassPathXmlApplicationContext ("XML/factory.xml");
        Curse curse = context.getBean ("Mybean", Curse.class);
        System.out.println (curse);

    }

IOC操作Bean管理(bean作用域)

​ 1、在Spring 里,默认情况下,创建的bean为单实例对象

 ApplicationContext context = new ClassPathXmlApplicationContext ("XMl/collectionInto.xml");
        Book book1 = context.getBean ("book", Book.class);
        Book book2 = context.getBean ("book", Book.class);
        System.out.println (book1==book2); //true 默认为单实例对象

​ 2、如何设置单实例还是多实例

​ 在Spring配置文件bean标签中有属性用于设置单实例还是多实例

<bean id="book" class="com.Spring5_demo2.collectiontype.Book" scope="singleton"> //单实例
<bean id="book" class="com.Spring5_demo2.collectiontype.Book" scope="prototype"> //多实例
        
    </bean>

​ 3、singleton 和 prototype的区别

​ ①singleton单实例,prototype多实例

​ ②设置scope值是singleton时,加载xml配置文件时就会创建单实例对象

​ 设置prototype时,并不是在加载xml配置文件时创建对象,而是在调用getbean方法时创建多实例的对象,每次创建的都是一个新的对象

​ scope 属性还有两个值 request session (作用同web)

IOC操作Bean管理(bean生命周期)

​ 1、bean的生命周期

​ ①通过构造器创建bean实例()

​ ②为bean的属性设置值和对其他bean的引用(调用set方法)

​ ③调用bean的初始化方法

​ ④bean可以获取

​ ⑤当容器关闭时,掉用bean中的销毁方法(需要自行配置)

当加入bean的后置处理器时,bean生命周期有七步 *

首先执行,bean的无参构造创建bean实例
第二步,调用set方法设置属性值
	*把bean的实例传递bean后置处理器的方法
第三步,执行初始化方法
	*把bean的实例传递bean后置处理器的方法
第四步,获取到了bean对象com.Spring5_demo2.factoryBean.Order@cb0ed20
第五步,销毁bean对象

IOC操作Bean管理(自动装配)

​ 1、什么时自动装配

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

 <!--实现自动装配 bean标签属性autowire
 属性值:
  //byName:根据属性名称进行注入,注入值bean的id值和类的属性名称一样
<bean id="emp" class="com.Spring5_demo2.autoWire.Emp" autowire="byName">
  <!--<property name="dept" ref="deptm"></property>-->
</bean>
<bean id="dept" class="com.Spring5_demo2.autoWire.Dept">
    </bean>
  //byType:根据属性类型进行注入
<bean id="emp" class="com.Spring5_demo2.autoWire.Emp" autowire="byType">
  <!--<property name="dept" ref="deptm"></property>-->
</bean>
<bean id="dept" class="com.Spring5_demo2.autoWire.Dept">  -->

IOC操作Bean管理(外部属性文件)

​ 1、直接配置数据库信息

​ ①配置druid连接池

​ 2、引入外部属性文件配置数据库连接池

​ ①创建外部属性文件(properties),填写数据库信息

​ ②将外部properties文件引入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"
       xmlns:util="http://www.springframework.org/schema/util"
       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/util http://www.springframework.org/schema/util/spring-util.xsd
         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">

​ ③获取properties文件内容,根据key获取,使用spring表达式获取

 	//jdbc.properties
	prop.driverClass=com.mysql.cj.jdbc.Driver
	prop.url=jdbc:mysql://localhost:3306/book
	prop.userName=root
	prop.password=wh.0410
     //druid.xml
	<context:property-placeholder location="classpath:jdbc.properties"/>
    <!-- 获取properties文件内容,根据key获取,使用spring表达式获取 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${prop.driverclass}"></property>
    <property name="url" value="${prop.url}"></property>
    <property name="username" value="${prop.username}"></property>
    <property name="password" value="${prop.password}"></property>
    </bean>

2--基于Spring注解方式实现

1、什么叫注解

​ ①注解是代码中的特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性值...)

​ ②使用注解,注解作用在类上面,方法上面

​ ③使用注解的目的:简化xml配置

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

①@Component

②@Service

③@Controller

④@Repository

​ 四个注解功能相同,都能用来创建bean实例

3、基于Spring注解实现对象的创建

​ 1.引入jar包

​ 2.开启组件扫描(扫描包中某个类的具体位置)

如果扫描多个包可以用 ’ ,‘ 隔开,也可以扫描这多个包的同一个上层目录

​ 3.创建类,在类上面添加创建对象注解

​ 4.注解中组件扫描的一些细节

 <!--开启组件扫描-->
    <context:component-scan base-package="com.Spring5_demo3"></context:component-scan>


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

        意思为扫描spring_demo3 中类型为注解 并且 注解为Controller的类
    -->

    <context:component-scan base-package="com.Spring5_demo3" use-default-filters="false">
            <context:include-filter type="annotation"
                    expression="org.springframework.stereotype.Controller"></context:include-filter>
    </context:component-scan>
    //-------------------------------------------------------    
<!--
    exclude-filter表示不包含,即设置哪些内容不进行扫描
-->
    <context:component-scan base-package="com.Spring5_demo3" use-default-filters="false">
        <context:exclude-filter type="annotation"
                                expression="org.springframework.stereotype.Controller"></context:exclude-filter>
    </context:component-scan>

4、基于注解的方式实现属性注入

​ ①@AutoWired:根据属性类型进行自动装配

​ 第一步,先创建目标类的对象,然后分别在类上标注注解

​ ②@Qualifier:根据属性的名称进行注入

​ 这个注解要和上面@AutoWired一起使用

​ ③@Resource:可以根据类型注入也可以根据名称注入

​ ④@Value:注入普通类型属性

5、Spring中的@Bean注解

spring的注解分类

从广义上讲,spring注解可以分为两类,一类注解是用于注册bean,一类注解用于使用bean。

假如ioc容器就是一间空屋子,首先这间空屋子里面啥也没有,我们要给这个空屋子添置家具的操作,就相当于每个注册bean的注解的作用,意思就是说,注册bean的注解作用,就是往ioc容器中放置(注册)东西。

用于注册bean的注解,比如@component、@repository、@controller、@service和@configration等,用途都是注册bean并放入到ioc容器中,一来是交给spring统一管理方便解耦,而来是可以重复使用,还是前面的例子,给空屋子添置的家具总不会都是一次性使用的,比如沙发,你只要一次注册了,每次想要休息就往上一躺就好了,而不是每次都到屋子外去搬进来(重新注册),节省了力气(重新注册的资源消耗),这也是为什么在spring里绝大部分bean都是单例模式的原因。

而用于使用bean的注解,比如@autowired、@resource等,用途都是从ioc容器中拿到注册好的bean以方便使用。使用这些注解的前提是ioc容器中有相应的被注册号的bean,如果ioc容器中没有,比如屋子里没有沙发,你还往地板上硬躺,就会很难受甚至受伤(报错)。

@bean注解概述

根据上面的分类,@bean注解应该归类于用于注册bean的注解。

为什么要有@bean注解呢?这是因为类似于@component、@repository、@controller和@service这些注册bean的注解都存在一定的局限性,局限于只能作用于自己编写的类,但是如果是一个jar包的第三方库要加入到ioc容器中的话,这些注解就无能为力了。为了解决这样的问题,@bean注解就产生了(当然了,还有@import注解也可以做到这一点,且更加方便快捷)。

@bean注解是被设计使用在方法上的,在方法上使用@bean注解的时候,该方法就会被告知去产生一个bean对象,然后这个bean对象交给spring管理,且产生这个bean对象的方法在整个spring的生命周期中只会被调用一次,调用完成之后spring会将这个bean对象放在自己的ioc容器中。

[复制代码](javascript:void(0)😉

class Yanggb {
    @Bean
    public YanggbDao createYanggbDaoBean(){
        return new YanggbDao();
    }
}

[复制代码](javascript:void(0)😉

在上面的例子中,createYanggbDaoBean方法就会产生一个YanggbDao对象,并将这个对象交给Spring管理(放到ioc容器中)。到这里很容易就能明白,@bean注解是使用在方法上的注解,它会明确地告诉被注解的方法去产生一个bean对象并交给spring容器管理。简单点说就是,@bean注解放在方法上,让方法去产生一个bean交给spring容器。

因为@bean注解是使用在方法上的,因此使用@bean注解的另一个好处就是能够动态获取一个bean对象,且能够根据环境不同得到不同的bean对象。

另外,@bean注解和xml配置中的bean标签的作用是一模一样的。

6、完全注解开发

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

 //注解类   
@Configuration
@ComponentScan(basePackages = {"com.Spring5_demo3"})
public class config {

}


  //测试
    @Test
    public void test()
    {
        ApplicationContext context = new AnnotationConfigApplicationContext (Config.class);
        UserService userService = context.getBean ("userService", UserService.class);
        userService.show ();
    }

3.AOP(面向切面编程)

1、 什么是AOP

​ (1)面向切面编程,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

​ (2)通俗来说AOP,就是不通过修改源代码,来增加功能。

image-20211030212945812

2、AOP底层原理

(1)AOP底层使用动态代理

​ ①有接口的情况,使用JDK动态代理

image-20211031092853518

​ ②没有接口的情况,使用CGLIB动态代理

image-20211031093954570

(2)AOP(JDK动态代理)

​ ①调用newProxyInstance(ClassLoader loader,类<?> [] interfaces,InvocationHandler h)方法

​ 方法有三个参数 :

​ 1-类加载器、2-增强方法所在的类,这个类实现的接口,支持多个接口

​ 3-实现这个接口InvocationHandler,创建代理对象,写增强的方法

package com.Spring5_demo4.AOP_Proxy;

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

public class JDKProxy {
    public static void main(String[] args) {
        //创建接口实现类代理对象
        Class[] interfaces = {UserDao.class};
        UserDaoimpl userDao = new UserDaoimpl ();
        UserDao dao = (UserDao)Proxy.newProxyInstance (JDKProxy.class.getClassLoader (), interfaces, new UserDaoProxy (userDao));
        int addres = dao.add (1, 2);
        System.out.println (addres);
    }

}
class UserDaoProxy implements InvocationHandler{
    //把创建的是谁的代理对象,就将谁传递过来 这里创建的是UserDao的代理对象
    private Object obj;
    public UserDaoProxy(Object object)
    {
        this.obj = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //方法之前进行处理
        System.out.println ("在方法之前执行--"+method.getName ()+"传递的参数:"+ Arrays.toString (args));
        //被增强的方法执行
        Object res = method.invoke (obj, args); //执行add后返回一个结果
        //方法之后
        System.out.println ("方法之后执行---"+obj);
        return res;
    }
}

(3)AOP术语

1、连接点

image-20211031153758654

2、切入点

​ 实际被真正增强的方法,称为切入点;

3、通知(增强)

​ ①实际增强的逻辑部分称为通知(增强)

​ ②通知有五种类型

1.前置通知 2.后置通知 3.环绕通知 4.异常通知 5.最终通知

4、切面

​ 将通知应用到切入点的过程;

(4)AOP操作准备

​ 1、Spring 框架一般基于AspectJ实现AOP操作

​ AspectJ不是Spring的组成部分,而是独立的AOP框架,一般把AspectJ和Spring框架整合使用,进行AOP操作

2、基于AspectJ实现AOP操作

​ ①基于xml配置文件方式实现

​ ②基于Spring注解方式实现(常用)

​ 3、在项目中引入AOP依赖

​ 4、切入点表达式

​ ①切入点表示式的作用:可以知道对哪个类的哪个方法进行增强

​ ②语法结构:execution([权限修饰符] [返回类型] [类全路径] [方法名称] [参数列表])

​ 包 . Student .*表示对Student类中的所有方法进行增强

​ 包 . * . *表示对包中的所有类的所有方法进行增强

(5)AOP操作

1、AspectJ注解方式(掌握)

​ ①编写增强类和被增强类

​ 在增强类中,创建方法,让不同方法代表不同通知类型

​ ②进行通知的配置

​ 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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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
                          http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--开启注解扫描-->
    <context:component-scan base-package="com.Spring5_AOP_annotation"></context:component-scan>
</beans>

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

​ 3.在增强类上面添加注解@Aspect

​ 4.在Spring配置文件中开启生成代理对象

​ ③配置不同类型的通知

​ 在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式来配置

package com.Spring5_AOP_annotation.bean;

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

/**
 * 增强类
 */
@Component
@Aspect //表示生成代理对象
public class UserProxy {
    /**
     * 前置通知
     * @Before注解就表示前置通知
     */
    @Before (value = "execution(* com.Spring5_AOP_annotation.bean.User.add(..))")
    public void before()
    {
        System.out.println ("before------");
    }

    /**
     * 最终通知 无论有没有异常都会执行
     */
    @After (value = "execution(* com.Spring5_AOP_annotation.bean.User.add(..))")
    public void after()
    {
        System.out.println ("after--------");
    }

    /**
     * 后置通知/返回通知 有异常不执行
     */
    @AfterReturning (value = "execution(* com.Spring5_AOP_annotation.bean.User.add(..))")
    public void afterReturning()
    {
        System.out.println ("AfterReturning--------");
    }

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

    /**
     * 环绕通知
     */
    @Around (value = "execution(* com.Spring5_AOP_annotation.bean.User.add(..))")
    public void Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println ("环绕之前......");

        //被增强的方法执行
        proceedingJoinPoint.proceed ();

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

​ 5.对公共切入点进行抽取

    @Around (value = "pointdemo()")
    public void Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println ("环绕之前......");

        //被增强的方法执行
        proceedingJoinPoint.proceed ();

        System.out.println ("环绕之后.......");
    }
    //相同切入点抽取
    @Pointcut(value = "execution(* com.Spring5_AOP_annotation.bean.User.add(..))")
    public void pointdemo()
    {

    }

​ 6.多个增强类对同一个方法进行增强,设置增强类优先级

​ 1、在增强类上面添加注解@Order,数字类型值越小优先级越高

2、AspectJ配置文件方式(了解)

<?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:aop="http://www.springframework.org/schema/aop"
       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
                          http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--创建俩个类的对象-->
        <bean id="book" class="com.Spring_AOP_XML.bean.book"></bean>
        <bean id="bookProxy" class="com.Spring_AOP_XML.bean.bookProxy"></bean>

    <aop:config>
        <!--//配置切入点表达式-->
        <aop:pointcut id="point" expression="execution(* com.Spring_AOP_XML.bean.book.buy(..))"></aop:pointcut>
        <!--配置切面-->
        <aop:aspect ref="bookProxy">
            <aop:before method="before" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
    
</beans>

4、数据库事务、JDBCTemplate

(1) 简介、测试

1.什么是JDBCTemplate

​ Spring框架对JDBC进行封装,使用JDBCTemplate方便实现对数据库的操作

2.在springxml文件中配置数据库连接池,配置JDBCTemplate对象注入Datasource

<context:property-placeholder location="classpath:jdbc.properties"/>
    <!-- 获取properties文件内容,根据key获取,使用spring表达式获取 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="${url}"></property>
        <property name="username" value="root"></property>
        <property name="password" value="wh.0410"></property>
    </bean>
    <!--扫描注解-->
    <context:component-scan base-package="com.Spring_JdbcTemplate"></context:component-scan>
    <!--JdbcTemplate对象-->
    <bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
        
        
   properties 文件
	driverClass=com.mysql.cj.jdbc.Driver
	url=jdbc:mysql://localhost:3306/test?&useSSL=false&serverTimezone=UTC
	userName=root
	password=wh.0410
        
     
  1. 测试类

        ApplicationContext context = new ClassPathXmlApplicationContext ("XML/Template/Te.xml");
            BookService bookService = context.getBean ("bookService", BookService.class);
            bookService.addBook (new Book ("1","三体","已售"));
    
    

(2)JDBCTemplate操作数据库(增删查改)

package com.Spring_JdbcTemplate.Dao;

import com.Spring_JdbcTemplate.entity.Book;

public interface BookDao {
    public void add(Book book);

    public void update(Book book);

    public void delete(String BookId);

}



package com.Spring_JdbcTemplate.Dao;


import com.Spring_JdbcTemplate.entity.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class BookDaoimpl implements BookDao{

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void add(Book book) {
        String sql = "insert into t_book values (?,?,?)";
        int update = jdbcTemplate.update (sql, book.getBookId (), book.getBookName (), book.getUstatus ());
        System.out.println (update);
    }

    @Override
    public void update(Book book) {
        String sql = "update t_book set BookName = ?,ustatus = ? where BookId = ?";
        int update = jdbcTemplate.update (sql, book.getBookName (), book.getUstatus (), book.getBookId ());
        System.out.println (update);
    }

    @Override
    public void delete(String BookId) {
        String sql = "delete from t_book where BookId = ?";
        jdbcTemplate.update (sql,BookId);
    }
}


package com.Spring_JdbcTemplate.Service;

import com.Spring5_demo3.Dao.UserDao;
import com.Spring_JdbcTemplate.Dao.BookDao;
import com.Spring_JdbcTemplate.Dao.BookDaoimpl;
import com.Spring_JdbcTemplate.entity.Book;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BookService {
    //注入dao
    @Autowired
    private BookDao bookDao;

    public void addBook(Book book)
    {
        bookDao.add(book);
    }
    public void updateBook(Book book)
    {
        bookDao.update(book);
    }
    public void DeleteBook(String BookId)
    {
        bookDao.delete(BookId);
    }

}

​ 1.JdbcTemplate查询返回某个值

 /**
     * 查询返回某个值
     * @return
     */
    @Override
    public Integer selectCount() {
        String sql = "select count(*) from t_book";
        Integer count = jdbcTemplate.queryForObject (sql, Integer.class);
        return count;
    }

​ 2.JdbcTemplate查询返回对象

/**
     * 返回对象
     * @param BookId
     * @return
     */
    @Override
    public Book queryOnebook(String BookId) {
        String sql = "select * from t_book where BookId = ?";
        Book book = jdbcTemplate.queryForObject (sql, new BeanPropertyRowMapper<Book> (Book.class), BookId);
        return book;
    }

​ 3.JdbcTemplate查询返回集合

/**
     * 查询返回集合
     * @return
     */
    public List<Book> queryBookList()
    {
        String sql = "select * from t_book";
        List<Book> books = jdbcTemplate.query (sql, new BeanPropertyRowMapper<Book> (Book.class));
        return books;
    }
	4.JdbcTemplate批量操作(批量添加修改删除)

image-20211103151827930

​ 参数一:sql语句 参数二:List集合,添加多条记录

 /**
     * 批量添加
     * @param batchArgs
     */
    public void batchAdd(List<Object[]> batchArgs)
    {
        String sql = "insert into t_book values(?,?,?)";
        int[] batchUpdate = jdbcTemplate.batchUpdate (sql, batchArgs);
        System.out.println (Arrays.toString (batchUpdate));
    }

    /**
     * 批量修改
     * @param batchArgs
     */
    public void batchUpdate(List<Object[]> batchArgs)
    {
        String sql = "update t_book set BookName=?,ustatus=? where BookId = ?";
        int[] batchUpdate = jdbcTemplate.batchUpdate (sql, batchArgs);
        System.out.println (Arrays.toString (batchUpdate));
    }

    /**
     * 批量删除
     * @param batchArgs
     */
    public void batchDelete(List<Object[]> batchArgs)
    {
        String sql = "delete from t_book where BookId = ?";
        int[] batchUpdate = jdbcTemplate.batchUpdate (sql, batchArgs);
        System.out.println (Arrays.toString (batchUpdate));
    }

(3)事务操作

1.什么是事务?

​ 事务是数据库操作的最基本单元,逻辑上一组操作,要莫都成功要么都失败。

2.事务的特性(ACID)

​ 原子性

​ 一致性

​ 隔离性

​ 持久性

3.事务环境

​ 数据库事务环境image-20211103161217985

4.事务的操作

​ 1-注意:事务一般添加到JavaEE三层结构的Service层上

​ 2-在Spring进行事务管理操作

​ 有两种方式 :编程式事务管理和声明式事务管理

开发中一般用声明式事务管理

​ 3-声明式事务管理

​ ①基于注解方式

​ ②基于xml配置文件方式

​ 4.在Spring进行声明式事务管理,底层使用AOP

​ 5.在Spring事务管理API

​ (1) 提供了一个接口,代表事务管理器。这个接口针对不同的框架提供了不同的实现类

​ 0-修改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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/util http://www.springframework.org/schema/util/spring-util.xsd
         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
         http://www.springframework.org/schema/tx http://www.springframework.org/schema/aop/spring-tx.xsd
">

​ (2)-创建事务管理器


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

​ (3)-开始事务注解

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

​ (4)-在service类上面(或者service类里面的方法上面添加事务注解)

​ ①@Transactional,这个注解添加到类的上面,也可以添加方法上面

​ ②如果把这个注解添加类的上面,这个类里面的所有方法都添加事务

​ ③如果把这个注解添加方法上面,位这个方法 添加事务

​ (5)事务注解中的参数

image-20211103210443430

​ 1-propagation :事务传播行为

​ 多事务方法直接进行调用,这个过程中事务时如何进行管理的

​ 事务方法:对数据库表数据进行变化的操作

image-20211103211634666

​ 2-Ioslation:事务隔离级别

​ ·1 事务有特性称为隔离性,多事务操作之间不会产生影响,不考虑隔离将会 产生很多问题

​ ·2 有三个读的问题 脏读、不可重复读、虚(幻)读

	![image-20211104174052000](C:\Users\未来可期\AppData\Roaming\Typora\typora-user-images\image-20211104174052000.png)

																				脏读

image-20211104174608491

​ 不可重复读

虚读:一个未提及的事务读取到了已提交事务中添加的数据

通过事务的隔离级别可以解决上述问题:

image-20211104175110262

​ Mysql默认隔离级别为REPEATABLE READ

​ 3-timeout:超过时间

​ 事务需要在一定的时间内进行提交,如果不提交就进行回滚

​ 默认值是- 1,设置时间以秒为单位进行计算

​ 4-readOnly:是否只读

​ 默认值为false,表示可以查询,可以进行添加修改删除操作

​ 如果设为true就只能查询

​ 5-rollbackFor:回滚

5.XML声明式事务管理

1.在spring配置文件中进行配置

​ ①配置事务管理器

​ ②配置通知

​ ③配置切入点和切面

<!--扫描注解-->
    <context:component-scan base-package="com.Spring_JdbcTemplate"></context:component-scan>
    <!--JdbcTemplate对象-->
    <bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--创建事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--配置通知-->
    <tx:advice id="txadvice">
        <!--配置事务的一些基本参数-->
        <tx:attributes>
            <!--指定哪种规则的方法上添加事务-->
            <tx:method name="accountMoney" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <!--配置切入点和切面-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="acc" expression="execution(* com.Spring_JdbcTemplate.Service.UserService.*(..))"></aop:pointcut>
        <!--配置切面-->
       <aop:advisor advice-ref="txadvice" pointcut-ref="acc"></aop:advisor>
    </aop:config>

2.完全注解声明式

​ ①创建配置类,使用配置类代替xml配置文件

package com.Spring_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;

@Configuration //配置类
@ComponentScan(basePackages = "com.Spring_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/test?&useSSL=false&serverTimezone=UTC");
        dataSource.setUsername ("root");
        dataSource.setPassword ("wh.0410");
        return dataSource;
    }

    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource)
    {
        JdbcTemplate jdbcTemplate = new JdbcTemplate ();
        //到IOC容器中根据类型找到dataSource 并注入dataSource
        jdbcTemplate.setDataSource (dataSource);
        return jdbcTemplate;
    }

    //创建事务管理器duix
    @Bean
    public DataSourceTransactionManager getdataSourceTransactionManager(DataSource dataSource)
    {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager ();
        //到IOC容器中根据类型找到dataSource 并注入dataSource
        dataSourceTransactionManager.setDataSource (dataSource);
        return dataSourceTransactionManager;
    }



}

​ ②创建测试方法

 @Test
    public void accountMoneyAnno()
    {
        ApplicationContext context = new AnnotationConfigApplicationContext (TxConfig.class);
        UserService userService = context.getBean ("userService", UserService.class);
        userService.accountMoney ();
    }

5、Spring5框架的新功能

1.增加功能

image-20211105105238567

2.核心特性

​ (1)@Nuallable注解可以使用在方法、属性、参数上面,表示方法返回可以为空,属性值可以为空

​ 参数值可以为空

​ (2)Spring5核心容器支持函数式风格GenericApplicationContext 创建对象

@Test
    public void  GenericApplicationContextTest()
    {
        //创建GenericApplicationContext对象
        GenericApplicationContext genericApplicationContext = new GenericApplicationContext ();
        //调用context方法对象注册
        genericApplicationContext.refresh ();

        genericApplicationContext.registerBean (Stu.class,()->new Stu ());

        //获取在Spring注册的对象
        Stu stu = (Stu) genericApplicationContext.getBean ("com.Spring_JdbcTemplate.Test.Stu");

        System.out.println (stu);
    }

(3)Spring5支持整合JUnit5

​ 1-整合JUnit4

@RunWith (SpringJUnit4ClassRunner.class) //指定单元测试框架
@ContextConfiguration("classpath:XML/Template/Te2.xml") //加载配置文件
public class JTest4 {
    @Autowired
    private UserService userService;

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

}

​ 2-整合JUnit5

@ExtendWith (SpringExtension.class)
@ContextConfiguration("classpath:XML/Template/Te2.xml")
public class JTest4 {
    @Autowired
    private UserService userService;

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

​ 3-使用复合注解整合上述俩个注解

@SpringJUnitConfig(locations = "classpath:bean1.xml")
public class JTest5 {
 @Autowired
 private UserService userService;
 @Test
 public void test1() {
 userService.accountMoney();
 } }

3.WebFlux

image-20211105165804832

(1)简单介绍

​ ①SpringWebFlux式Spring5新加的模块,用于web开发,与SpringMVC功能类似,WebFlux使用

当前一种比较流行的响应式编程出现的框架

​ ②使用传统web框架,比如SpringMVC,这些基于Servlet容器,WebFlux是一种一部非阻塞的框架,异步非阻塞的框架再Servlet3.1以后才支持,核心是基于reactor的相关API实现

​ ③异步非阻塞:

​ 异步、同步:调用者发送请求,如果要等着对方回应后才能做其他事情则称为同步,若发送请求后可以不等待回应就去做其他事情称为异步(Ajax就是异步请求,局部改变动态页面)

​ 阻塞、非阻塞:被调用者收到请求后,在做完请求任务后才给出反馈就是阻塞,若收到请求后马上就做出反馈就是非阻塞

​ ④WebFlux的特点:

​ 1-非阻塞式:可以在有限的资源下,提高系统的吞吐量和伸缩性(即在有限的 资源下处理更多的请求)

​ 2-函数式编程:Spring框架基于java8,WebFlux使用java8函数时编程方式实现路由请求

image-20211105191115266

(2)响应式编程

​ 何为响应式编程是一种面向数据流和变化传播的编程范式,这意味着可以在编程语言中很方便的表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播

(3)WebFlux 执行流程和核心API

(4)SpringWebflux(基于注解编程模型)

(5)SpringWebflux(基于函数式编程模型)

	先看看springmvc boot 后再回头看5的新特性

尚硅谷Spring5框架教程(idea版)_哔哩哔哩_bilibili

posted @   苏澜  阅读(119)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示