1. 回顾
线程死锁概念和如何避免死锁的发生:
线程的通信 wait notify() notify():---Object类
线程的状态: NEW--->start()--->就绪状态---CPU时间片---运行状态RUNNABLE]--->sleep()--->TIMED_WAITING--->wait()---->WAITING----sysn---Blocked---->终止状态[T]
线程池: 常见的线程池种类: 4种和原始
2. 正文 (3W+1H what why where How)
- 1. 什么是AOP?
- 2. 为什么使用AOP?
- 3. 如何使用AOP?
- 4. 什么是事务?
- 5. spring如何实现事务管理。
复制代码 3. 什么是AOP?
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP:它是面向切面编程的语言,它可以让你的业务代码和非业务代码进行隔离。在不改变业务代码的前提下,可以增加新的非业务代码。
4. 为什么使用AOP
5. AOP应用场景
6. AOP的结构
AOP要做的三件事在哪里切入,也就是权限校验,等非业务操作在哪些业务 代码中执行;什么时候切入,是业务代码执行前还是执行后;切入后做什 么事,比如做权限校验、日志记录等。
- Aspect: 切面
- PointCut:切点:---方式: 路径表达式 (2)注解形式
- Advice: 处理的时机。
7. 如何使用AOP
案例- public class MathServiceImpl implements MathService {
- public double add(double a, double b) {
- double result=a+b;
- System.out.println("AAA--->The add method result="+result);
- return result;
- }
- public double mul(double a, double b) {
- double result=a-b;
- System.out.println("AAA--->The mul method result="+result);
- return result;
- }
- public double cheng(double a, double b) {
- double result=a*b;
- System.out.println("AAA--->The cheng method result="+result);
- return result;
- }
- public double div(double a, double b) {
- double result=a/b;
- System.out.println("AAA--->The div method result="+result);
- return result;
- }
- }
复制代码发现: 我们在每个操作后,都要记录日志,如果后期日志内容发生改变。需要在每个操作后都进行修改。 不利于代码的维护。
我们来使用AOP来解决。
(1)引入相关依赖- <dependencies>
-
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-webmvc</artifactId>
- <version>5.2.12.RELEASE</version>
- </dependency>
-
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-aspects</artifactId>
- <version>5.2.12.RELEASE</version>
- </dependency>
- </dependencies>
复制代码 (2)创建一个切面类- @Aspect //标记该类为切面类
- @Component //该类对象的创建交于spring容器来管理-----等价于@Service @Controller
- public class MyAspect {
- @Pointcut(value = "execution(public double com.ykq.aop.MathServiceImpl.add(double, double))") //定义为切点
- private void mypointcut(){}
- @After(value = "mypointcut()")
- public void b(){
- System.out.println("AAA--->The add method result");
- }
- }
复制代码 (3) 创建一个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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
-
- <context:component-scan base-package="com.ykq.aop"/>
-
- <aop:aspectj-autoproxy/>
- </beans>
复制代码 (4)测试- public class Test {
- public static void main(String[] args) {
- //加载spring配置文件
- ApplicationContext app=new ClassPathXmlApplicationContext("classpath:spring.xml");
- MathService mathServiceImpl = (MathService) app.getBean("mathServiceImpl");
- System.out.println(mathServiceImpl.add(20, 10));
- }
- }
复制代码 使用通配符来统配类路径- @Aspect //标记该类为切面类
- @Component //该类对象的创建交于spring容器来管理-----等价于@Service @Controller
- public class MyAspect {
- //通配符:
- /**
- * 第一个* : 表示任意修饰符 任意返回类型。
- * 第二个* : 表示该包下所有的类。
- * 第三个* : 类下所有的方法
- * ..: 表示任意参数
- *
- * 建议包就别使用统配符
- */
- @Pointcut(value = "execution(* com.ykq.aop.*.*(..))") //定义为切点
- private void mypointcut(){}
- @After(value = "mypointcut()")
- public void b(){
- System.out.println("AAA--->The add method result");
- }
- }
复制代码 7.2 注解模式
(1)自定义注解- @Target(value = {ElementType.METHOD,ElementType.TYPE})
- @Retention(RetentionPolicy.RUNTIME)
- public @interface MyAnnotation {
- String value() default "";
- }
复制代码 (2)修改切面类- @Pointcut(value = "@annotation(com.ykq.aop.MyAnnotation)") //定义为切点
- private void mypointcut2(){}
- //在使用MyAnntation注解的方法之后执行内容
- @After(value = "mypointcut2()")
- public void b(){
- System.out.println("AAA--->The add method result");
- }
复制代码 7.3 aop切面通知的类型
- package com.aaa.aop;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.*;
- import org.springframework.stereotype.Component;
- @Aspect //标记该类为切面类
- @Component //该类对象的创建交于spring容器来管理-----等价于@Service @Controller
- public class MyAspect {
- //通配符:
- /**
- * 第一个* : 表示任意修饰符 任意返回类型。
- * 第二个* : 表示该包下所有的类。
- * 第三个* : 类下所有的方法
- * ..: 表示任意参数
- *
- * 建议包就别使用统配符
- */
- @Pointcut(value = "execution(* com.ykq.aop.*.*(..))") //定义为切点
- private void mypointcut(){}
- @Pointcut(value = "@annotation(com.ykq.aop.MyAnnotation)") //定义为切点
- private void mypointcut2(){}
- // //在使用MyAnntation注解的方法之后执行内容。无论如何都执行。
- // @After(value = "mypointcut()")
- // public void a(){
- // System.out.println("AAA--->The add method result");
- // }
- //
- // //前置通知:
- // @Before(value = "mypointcut()")
- // public void b(){
- // System.out.println("========方法执行前执行切面的内容 前置通知===========");
- // }
- //
- // //后置返回通知. 碰到return. 如果方法出现异常;这种通知不会被执行
- // @AfterReturning(value = "mypointcut()",returning = "r") //returnning它会把方法执行的结果赋值给该变量
- // public void afterReturning(Object r){ //参数名必须和returning的名称一致
- // System.out.println("~~~~~~~~~~~~~~~~~~后置返回通知~~~~~~~~~~~~~~~~"+r);
- // }
- //
- // //异常通知: 当被切入的方法出现异常时,才会执行
- // @AfterThrowing(value = "mypointcut()")
- // public void afterThrowable(){
- // System.out.println("==============异常通知===========================");
- // }
- //环绕通知。
- @Around(value = "mypointcut()")
- public Object around(ProceedingJoinPoint joinPoint){//joinPoint:连接点 理解为被执行的方法对象
- System.out.println("业务代码执行前执行的内容======================");
- try {
- Object result = joinPoint.proceed();//执行你的连接点
- System.out.println("方法执行完毕后~~~~~~~~~~~~~~~~~");
- return result;
- } catch (Throwable throwable) {
- throwable.printStackTrace();
- System.out.println("方法出现异常时执行~~~~~~~~~~~~~");
- }finally{
- System.out.println("无论如何都会执行");
- }
- return 0.0;
- }
- }
复制代码@Before 前置通知. 被代理的方法执行前--执行
@After: 后置通知: 被代理的方法执行完后--执行
@AfterReturning: 后置返回通知: 被代理的方法碰到return.--才会执行
@AfterThrowing: 后置异常通知: 当被代理的方法出现异常时--才会执行。
@Around: 环绕通知。
8. spring如何操作事务
8.1 什么是事务?
事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用.
例子: 转账
扣钱和加钱----要么都执行要么都不执行。
JDBC----它模式事务自动提交的。
- public class Test { public static void main(String[] args) { Connection conn=null; try { Class.forName("com.mysql.cj.jdbc.Driver"); conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/aaa?serverTimezone=Asia/Shanghai","root","root"); conn.setAutoCommit(false);//设置事务手动提交。 PreparedStatement ps=conn.prepareStatement("update t_user set balance=balance-600 where id=7"); ps.executeUpdate(); //int i=10/0; PreparedStatement ps2=conn.prepareStatement("update t_user set balance=balance+600 where id=6"); ps2.executeUpdate(); conn.commit();//事务提交 }catch (Exception e){ e.printStackTrace(); //事务回滚 try {<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
-
- <context:component-scan base-package="com.ykq.aop"/>
-
- <aop:aspectj-autoproxy/>
- </beans>conn.rollback(); } catch (SQLException throwables) {<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
-
- <context:component-scan base-package="com.ykq.aop"/>
-
- <aop:aspectj-autoproxy/>
- </beans>throwables.printStackTrace(); } }finally { } }}
复制代码 8.2 spring如何实现事务
spring框架一定会提供一个事务切面类。【1】前置通知---开启手动事务 [2]后置返回通知[事务提交] [3]异常通知[事务回滚]
(1)依赖(2)spring配置文件(3) dao类和xml- public interface UserDao {
- //1.修改账号余额
- public void updateBalance(@Param("id") int id, @Param("money") double money);
- }
复制代码- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.ddd.dao.UserDao">
- <update id="updateBalance">
- update t_user set balance=balance+#{money} where id=#{id}
- </update>
- </mapper>
复制代码 (4)service- package com.ddd.service.impl;
- import com.ddd.dao.UserDao;
- import com.ddd.service.UserService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- @Service
- public class UserServieImpl implements UserService {
- @Autowired
- private UserDao userDao;
- @Transactional //该方法交于spring的事务来管理了---默认spring不识别该注解
- public void zhuanzhang(int id, int uid, double money) {
- //1.扣钱
- userDao.updateBalance(id,-money);
- //int c=10/0;
- //2.收钱
- userDao.updateBalance(uid,money);
- }
- }
复制代码 (5)测试:- public class Test {
- public static void main(String[] args) {
- ApplicationContext app=new ClassPathXmlApplicationContext("classpath:spring.xml");
- UserService userServieImpl = (UserService) app.getBean("userServieImpl");
- userServieImpl.zhuanzhang(7,6,400);
- }
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |