Spring 与 Servlet-2

学习笔记(加油呀):

Spring的通知类型

Spring 通知类型按切面功能调用的不同时刻,可以分为提供了 5 种 Advice 类型

1、前置通知 Before advice:在某连接点之前执行的通知,但这个通知不能阻止连接点之前的执行流程(除非它抛出一个异常)

2、后置通知 After returning advice:在某连接点正常完成后执行的通知

3、异常通知 After throwing advice:在方法抛出异常退出时执行的通知

4、最终通知 After (finally) advice:当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)

5、环绕通知 Around Advice:包围一个连接点的通知,如方法调用。这是最强大的一种通知类型。环绕通知

可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它自己的返回值或抛出异常来结束执行

通知类型的选择

1、环绕通知是最常用的通知类型

2、推荐使用尽可能简单的通知类型来实现需要的功能

3、如果你只是需要一个方法的返回值来更新缓存,最好使用后置通知而不是环绕通知

4、用最合适的通知类型可以使得编程模型变得简单,并且能够避免很多潜在的错误

依赖:spring-aop 和 spring-aspects

应用开发 1:在访问 UserServImpl 具体实现类中方法时需要记录日志【应该使用日志记录器,例如 log4j,这里简化为控制台输出】

public class LogAdvice{public void before(){System.out.println("before...");}
}

配置这个通知类对象,同时引入 aop 名空间用于配置拦截规则

<bean id = "LodAdvice" class = "com.ma.aop.LogAdvice"/>
<aop:config><!--定义切面--><aop:aspect ref="logAdvice"><aop:pointcut id = "bbc" expression = "execution(* com.ma.biz.*.*(..))"/><aop:before method = "before" pointcut-ref="bbc"/></aop:aspect>
</aop:config>

可以使用连接点对象 JoinPoint 获取当前拦截的连接点相关信息,但是除非是原地修改否则修改传入数据无效;不能决定程序是否继续执行,除非人为抛出异常阻止继续执行

public class LogAdvice(){public void before(JoinPoint joinPoint){System.out.println("before...");Object target = joinPoint.getTarget();System.out.println("调用的目标对象为"+target);Signature signature = joinPoint.getSignature();System.out.println("方法签名为:"+ signature.getName());Object[] args = joinPoint.gteArgs();System.out.println("调用的方法参数为:" + args);}
}

应用 2:修改业务方法的返回值,将口令修改为等长星号

AfterReturning 可以原地修改返回值,但是如果不是原地修改,则修改无效

public class PasswordAspect{public void changePassword(List<User> userList){for(User tmp:userList){tmp.setPassword(changePwd(tmp.getPassword()));}}private String changePwd(String Pwd){StringBuilder sb = new StringBuilder();for(int i = 0;i < pwd.length();i++)sb.append("*");return sb.toString();}
}

applicationContext.xml 配置

<bean id = "PwdAspect" class = "com.ma.aop.PasswordAspect"/>
<aop:config><aop:aspect ref="PwdAspect"><aop:pointcut id = "bbc" expression = "execution(java.util.List com.ma.biz.*.getAllUsers())"/><aop:before method = "changePassword" pointcut-ref="bbc" returning = "userList"/></aop:aspect>
</aop:config>

应用 3:无所不能的环绕通知

环绕通知可以在方法执行前执行,可以修改传入参数,可以决定是否执行目标程序,可以在方法执行后执行,可以修改返回值,可以捕获异常并消费掉,可以使用 try/finally 结构定义最终需要执行的程序

@Override
public String hello(String name){System.out.println("业务方法参数:" + name);String res = "Hello"+name+"!";System.out.println("业务方法返回值:" + res);return res;
}

定义对应的切面类

public class AroundAspect{//如果需要获取请求相关信息,则需要在方法中添加一个参数ProceedingJoinPointpublic Object aaa(ProceedingJoinPoint pjp){Object res = null;try{System.out.println("前置处理程序....");Signature signature = pjp.getSignature();//方法签名Object target = pjp.getTarget();//目标对象Object[] args = pjp.getArgs();//获取调用方法的请求参数if(args!=null && args.length>0){args[0] = "修改传入参数";}//pjp.proceed() 用于不修改参数的继续向后执行,下一个是目标对象,还是下一个切面res = pjp.proceed(args);//用于修改请求参数System.out.println("返回后置处理程序...");res = "修改返回值:"+res;}catch(Throwable exception){System.out.println("异常处理程序...");}finally{System.out.println("最终处理程序...");}return res;}
}

对应配置

<bean id = "aroundAspect" class = "com.ma.aop.AroundAspect"/>
<aop:config><aop:aspect ref="aroundAspect"><aop:pointcut id = "bbc" expression = "execution(java.lang.String *.he*.*(java.lang.String))"/><aop:before method = "aaa" pointcut-ref="bbc"/></aop:aspect>
</aop:config>

注意:事实上在环绕通知中甚至可以执行其它程序,而不执行真正调用的方法

斑鸠蛋模式:阳奉阴违

具体应用:

一般针对控制层建议使用 Filter 之类的 AOP 实现;针对业务层建议使用 Spring AOP,针对持久层的 Mybatis还是优先考虑 MyBatis 的拦截器 Interceptor

使用 AOP 三种方式

1、通过 Spring 的 API 实现 AOP。实现前置通知接口 MethodBeforeAdvice / 后置通知 AfterReturningAdvice / 环绕通知 MethodInterceptor / 最终通知 AfterAdvice / 异常通知 AfterThrowingAdvice 等特定的接口

<bean id="log" class="com.ma.Log"/>
<bean id="afterLog" class="com.ma.AfterLog"></bean>
<aop:config>

切入点,需要告诉方法在什么去执行。expression="execution(* com.ma..(…))"其中第一个* 表示所有的返回值,然后就是包名。第二个表示所有的类对象。第三个表示类对象所有的方法。第四个*表示所有方法下面的带参数的方法或者是不带参数的方法

    <aop:pointcut expression="execution(* com.ma.*.*(..))" id="pointcut"/><aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
</aop:config>

Spring AOP 的工作原理【面试】

Spring 框架中的 AOP 拦截技术是 POJO 的方法层面的拦截【拦截的颗粒度较粗】。其底层实现原理是动态代理技术。对于面向接口的方法拦截,依赖于 jdk 的动态代理技术,即 java.lang.reflect.Proxy#newProxyInstance,

将对被代理的目标对象的调用,委托到代理对象,触发拦截通知;而当被拦截的方法, 不是在接口中定义时,使用的是 cglib,对字节码进行动态增强,生成被代理类的子对象,以实现代理spring 实现 aop,动态代理技术的两种实现是 jdk 动态代理、cglib 代理,根据被通知的方法是否为接口方法,来选择使用哪种代理生成策略

1、jdk 动态代理,原理是实现接口的实例,拦截定义于接口中的目标方法,性能更优,是 spring 生成代理的优先选择

2、cglib 代理,原理是使用 cglib 库中的字节码动态生成技术,生成被代理类的子类实例,可以拦截代理类中的任一 public 方法的调用,无论目标方法是否定义于接口中,更通用,但性能相对 jdk 代理差一些;

在这里插入图片描述

2、自定义类来实现 AOP,不实现 spring 的自带的通知

<bean id="userService" class="com.ma.UserServiceImpl"/>
<bean id="log" class="com.yan.Log"/>切面也要配置成 bean
<aop:config><aop:aspect ref="log"><aop:pointcut expression="execution(* com.ma.*.*(..))切入点表达式" id="pointcut"/><aop:before method="before 切面类中的方法名" pointcut-ref="pointcut"/><aop:after method="after 切面类中的方法名" pointcut-ref="pointcut"/></aop:aspect>
</aop:config>

3、通过注解实现 AOP

首先切面类需要定义为受管 bean,也就是 xml 配置或者使用@Component 注解+自动扫描

@Aspect
public class Log {        @Before("execution(* com.ma.*.*(..))") //前置处理程序public void before(JoinPoint jp){System.out.println("方法执行前"); }@After("execution(* com.ma.*.*(..))") //最终处理程序public void after(){System.out.println("方法执行后"); }@Around("execution(* com.ma.*.*(..))") //环绕处理程序public Object around(ProceedingJoinPoint jp) throws Throwable{System.out.println("环绕前");System.out.println("方法"+jp.getSignature());Object result=jp.proceed();System.out.println("环绕后");return result; }
}

对应配置

<bean id="log" class="com.ma.Log"/>
<aop:aspectj-autoproxy/> 打开自动代理

5 种常见注解

1、@Before 前置通知, 在方法执行之前执行

2、@After 最终通知, 在方法执行之后执行

3、@AfterRunning 后置通知, 在方法返回结果之后执行

4、@AfterThrowing 异常通知, 在方法抛出异常之后

5、@Around 环绕通知, 围绕着方法执行

复习了一下MyBatis 整合 Spring

1、添加依赖 mybatis、mybatis-spring,另外不使用 mybatis 提供的连接池,而是使用产品级连接池 druid,所以添加依赖 druid 以及数据库驱动

2、定义表结构,从输入页面上进行总结

create table if not exist tbl_users(id bigint primary key auto_increment,username varchar(32) not null unique,password varchar(32) not null,hiredate timestamp default current_timestamp comment '入职时间',sex boolean default 1
)engine=innodb default charset utf8;

3、使用反向映射插件 mybatis-generator-maven-plugin 进行反向映射,生成实体类、mapper 接口和 mapper.xml映射元文件

添加反向映射的配置文件,可以从网络中获取,也可以从旧有项目中进行拷贝修改

在这里插入图片描述

生成的映射元文件 UserMapper.xml、实体类 User 和映射接口 UserMapper

在这里插入图片描述

4、修改映射生成的类、接口和 xml 文件

实体类

@Data
public class User implements Serializable{private Long id;private String username;private String password;private Data hiredata;private Boolean sex;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/9737.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决vmWare ESXI 7.3报错,客户机操作系统已禁用 CPU。请关闭或重置虚拟机(ESXI使用遇到问题解决记录文持续使用持续更新)

一&#xff1a;分析客户机操作系统已禁用 CPU" 这个错误通常是由以下原因之一引起的&#xff1a; 1. 虚拟机配置不正确&#xff1a;可能是您在虚拟机配置中选择了不受支持的 CPU 类型或功能。某些操作系统可能需要特定的 CPU 功能才能正常运行。如果您的虚拟机配置与操作…

关于windows本机开放端口后,同一个网络下的其他电脑telnet不通的解决办法

前提&#xff1a;电脑A与电脑B均在同一个wifi下。 本地电脑A 启动了一个kong网关&#xff08;不管是什么应用&#xff0c;只要开启了一个监听端口就行&#xff09;&#xff0c;并且将docker里面的8000端口映射到本机的8000端口&#xff0c; 此时在电脑A上的命令行运行&#xf…

github Couldn‘t connect to server

Couldnt connect to server 问题描述解决git clone 出错直接访问github没啥问题ping github.com手动指定域名映射关系再次测试git命令 总结参考 问题描述 前一天还是好好的&#xff0c;能git pull和git push&#xff0c;昨天回来之后怎么操作都是Couldnt connect to server。百…

小程序 web-view h5页面背景音乐自动播放

/*** 年度账单-登录首页*/ import React,{useEffect} from react import swiper/swiper-bundle.min.css import styles from ./styles.less import bgm from ./bgm2.mp3 // 主体 const annualAccountLoginIndex (props) > {const goAnnualAccount ()>{const {location: …

Methodot低代码开发教程——玩转表格增删改查分页

目录 1、背景介绍 2、连接数据源 2.1 新增数据源 2.2 填写数据源信息 3、表格数据的展示 3.1 新增查询&#xff0c;编写查询语句 3.2 使用表格组件 3.3 同步数据源与表格列名 4、表格的数据新增 4.1 新增查询&#xff0c;编写新增语句 4.2 表格配置新增一行&#xff0…

centos7系统一键离线安装docker

离线安装脚本 # 离线安装docker rpm -Uvh --force --nodeps *.rpm # 启动docker systemctl start docker sudo systemctl daemon-reload # 设置开机自动启动docker systemctl enable docker.service下载 程序包下载地址 https://gitcode.net/zenglg/centos7_docker_offline_…

Spring BeanFactory FactoryBean的区别?

文章目录 前言一、BeanFactory二、FactoryBean 前言 面试中被问到过Spring BeanFactory FactoryBean的区别&#xff1f;当时没答上来&#xff0c;感觉这就是一个文字游戏&#xff0c;后面仔细的了解了一下&#xff0c;分享给大家。 一、BeanFactory 在 Spring 中最核心的就是…

HJ76 尼科彻斯定理

描述 验证尼科彻斯定理&#xff0c;即&#xff1a;任何一个整数m的立方都可以写成m个连续奇数之和。 例如&#xff1a; 1^31 2^335 3^37911 4^313151719 输入一个正整数m&#xff08;m≤100&#xff09;&#xff0c;将m的立方写成m个连续奇数之和的形式输出。 数…

Linux进度条

Linux进度条 一.基本概念1.回车和换行2.缓冲区2.实现倒计时 二.进度条1.前置工作2.代码实现 一.基本概念 1.回车和换行 回车&#xff1a;指光标移到该行的起始位置&#xff08;\r&#xff09;。 换行&#xff1a;换到下一行&#xff08;\n&#xff09;。 在c语音里\n将回车和换…

Jvm内存模型剖析优化-JVM(四)

上篇文章代码实例详解如何自定义双亲委派&#xff0c;主要实现ClassLoader&#xff0c;有两个方法&#xff0c;一个直接loadClass用父类的&#xff0c;如果想在破坏&#xff0c;则需要重写loadClass&#xff0c;一个findClass必须要重新&#xff0c;因为父类是空的&#xff0c;…

arcgis的属性显示bug

arcgis中&#xff0c;右键图层属性可以查看图层的属性信息&#xff0c;比如坐标系、波段数、行列数等。 但是今天实验的时候发现&#xff0c;这个属性中显示的波段最大最小值并非真值。 该图层实际范围为&#xff1a;30~711。 在arcgis属性中&#xff0c;显示范围为0~651。 在…

前端技术搭建五子棋游戏(内含源码)

The sand accumulates to form a pagoda ✨ 写在前面✨ 功能介绍✨ 页面搭建✨ 样式设置✨ 逻辑部分 ✨ 写在前面 上周我们实通过前端基础实现了拼图游戏&#xff0c;今天还是继续按照我们原定的节奏来带领大家完成一个五子棋游戏&#xff0c;功能也比较简单简单&#xff0c;也…