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解析、工厂模式、反射
(2)IOC过程:
降低耦合度:如当Dao路径发生改变时,只需要修改xml配置文件中的 class属性就可以
(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、把特殊符号进行转义 < >
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,就是不通过修改源代码,来增加功能。
2、AOP底层原理
(1)AOP底层使用动态代理
①有接口的情况,使用JDK动态代理
②没有接口的情况,使用CGLIB动态代理
(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、连接点
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
-
测试类
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批量操作(批量添加修改删除)
参数一: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.事务环境
数据库事务环境
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)事务注解中的参数
1-propagation :事务传播行为
多事务方法直接进行调用,这个过程中事务时如何进行管理的
事务方法:对数据库表数据进行变化的操作
2-Ioslation:事务隔离级别
·1 事务有特性称为隔离性,多事务操作之间不会产生影响,不考虑隔离将会 产生很多问题
·2 有三个读的问题 脏读、不可重复读、虚(幻)读

脏读
不可重复读
虚读:一个未提及的事务读取到了已提交事务中添加的数据
通过事务的隔离级别可以解决上述问题:
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.增加功能
除
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
(1)简单介绍
①SpringWebFlux式Spring5新加的模块,用于web开发,与SpringMVC功能类似,WebFlux使用
当前一种比较流行的响应式编程出现的框架
②使用传统web框架,比如SpringMVC,这些基于Servlet容器,WebFlux是一种一部非阻塞的框架,异步非阻塞的框架再Servlet3.1以后才支持,核心是基于reactor的相关API实现
③异步非阻塞:
异步、同步:调用者发送请求,如果要等着对方回应后才能做其他事情则称为同步,若发送请求后可以不等待回应就去做其他事情称为异步(Ajax就是异步请求,局部改变动态页面)
阻塞、非阻塞:被调用者收到请求后,在做完请求任务后才给出反馈就是阻塞,若收到请求后马上就做出反馈就是非阻塞
④WebFlux的特点:
1-非阻塞式:可以在有限的资源下,提高系统的吞吐量和伸缩性(即在有限的 资源下处理更多的请求)
2-函数式编程:Spring框架基于java8,WebFlux使用java8函数时编程方式实现路由请求
(2)响应式编程
何为响应式编程是一种面向数据流和变化传播的编程范式,这意味着可以在编程语言中很方便的表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播
(3)WebFlux 执行流程和核心API
(4)SpringWebflux(基于注解编程模型)
(5)SpringWebflux(基于函数式编程模型)
先看看springmvc boot 后再回头看5的新特性
尚硅谷Spring5框架教程(idea版)_哔哩哔哩_bilibili
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗