Spring-AOP配置及底层原理
发布日期:2022-02-10 11:36:58 浏览次数:46 分类:技术文章

本文共 5285 字,大约阅读时间需要 17 分钟。

Spring AOP的几个概念

1.切面(Aspect):切面就是一个关注点的模块化,如事务管理、日志管理、权限管理等;

2.连接点(Joinpoint):程序执行时的某个特定的点,在Spring中就是一个方法的执行;

3.通知(Advice):通知就是在切面的某个连接点上执行的操作,也就是事务管理、日志管理等;

4.切入点(Pointcut):切入点就是描述某一类选定的连接点,也就是指定某一类要织入通知的方法;

5.目标对象(Target):就是被AOP动态代理的目标对象;

AOP的通知类型

◆ 前置通知:原始方法执行前执行,如果通知中抛出异常,阻止原始方法运行

应用:数据校验

◆ 后置通知:原始方法执行后执行,无论原始方法中是否出现异常,都将执行通知

应用:现场清理

◆ 返回后通知:原始方法正常执行完毕并返回结果后执行,如果原始方法中抛出异常,无法执行

应用:返回值相关数据处理

◆ 抛出异常后通知:原始方法抛出异常后执行,如果原始方法没有抛出异常,无法执行

应用:对原始方法中出现的异常信息进行处理

◆ 环绕通知:在原始方法执行前后均有对应执行执行,还可以阻止原始方法的执行

应用:十分强大,可以做任何事情

注意:当同一个切入点配置了多个通知时,通知会存在运行的先后顺序,该顺序以通知配置的顺序为准

AOP配置之纯注解方式

简易配置类

@EnableAspectJAutoProxy@Configuration@ComponentScan("com.project")@Component@Aspect//切面public class Aops {
@Pointcut("execution(* *..*(..))")//切入点 public void pt(){
}; @Before("pt()")//通知 public void strong(){
System.out.println("增强方法"); }}

接口和实现类

//接口public interface StudentService {
void find();}//--------------------------------------------------------------//实现类@Componentpublic class StudentServiceImpl implements StudentService {
public void find() {
System.out.println("找到了该学生"); }}

测试类

public class StudentServiceTest {
@Test public void testFind() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Aops.class); StudentService bean = (StudentService) ctx.getBean(StudentService.class); bean.find(); }}打印结果: 增强方法 找到了该学生

注解开发AOP注意事项

  1. 切入点最终体现为一个方法,无参无返回值,无实际方法体内容,但不能是抽象方法
  2. 引用切入点时必须使用方法调用名称,方法后面的()不能省略
  3. 切面类中定义的切入点只能在当前类中使用,如果想引用其他类中定义的切入点使用“类名.方法名()”引用
  4. 可以在通知类型注解后添加参数,实现XML配置中的属性,例如after-returning后的returning属性

AOP配置之配置文件方式

spring配置文件

接口和实现类

//接口public interface StudentService {
void find();}//--------------------------------------------------------------//实现类@Componentpublic class StudentServiceImpl implements StudentService {
public void find() {
System.out.println("找到了该学生"); }}

通知类

public class Aops {
public void strong(){
System.out.println("增强方法"); }}

测试类

public class StudentServiceTest {
@Test public void testFind() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); StudentService bean = (StudentService) ctx.getBean("service"); bean.find(); }}打印结果: 增强方法 找到了该学生

AOP底层原理

SpringAOP底层使用了动态代理,spring框架会生成并管理代理类,

spring框架对于这种编程思想的实现基于两种动态代理模式,分别是 JDK动态代理 及 CGLIB的动态代理,这两种动态代理的区别是 JDK动态代理需要目标对象实现接口,而 CGLIB的动态代理则不需要。

接口及其实现类

//接口public interface PersonService {
void show();}//实现类public class PersonServiceImpl implements PersonService {
public void show() {
System.out.println("毛坯房"); }}

jdk动态代理

package com.project.proxy;import com.project.service.PersonService;import com.project.service.impl.PersonServiceImpl;import java.lang.reflect.Proxy;public class ProxyPersonService {
public static void main(String[] args) {
/** * personService:目标对象 * 使用jdk动态代理生成代理类 */ final PersonService personService = new PersonServiceImpl(); PersonService proxyInstance = (PersonService) Proxy.newProxyInstance( //目标对象的类加载器 PersonServiceImpl.class.getClassLoader(), //目标对象实现的接口 PersonServiceImpl.class.getInterfaces(), //第三个参数InvocationHandler接口实现类,用来封装额外功能,这里用的是lambda表达式 (proxy, method, param) -> {
Object invoke = method.invoke(personService, param); System.out.println("精装修"); return invoke; } ); proxyInstance.show(); }}打印结果: 毛坯房 精装修

cglib

package com.project.Cglib;import com.project.service.PersonService;import com.project.service.impl.PersonServiceImpl;import org.junit.Test;import org.springframework.cglib.proxy.Enhancer;import org.springframework.cglib.proxy.MethodInterceptor;public class CglibProxyTest {
@Test public void TestCglibProxy() {
/** * 使用cglib代理生成代理类 */ //创建Enhancer对象 Enhancer enhancer = new Enhancer(); //设置enhancer的父类为指定类型,这里就是我们需要代理的类 enhancer.setSuperclass(PersonServiceImpl.class); //回调方法过滤 enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
//执行原来的方法 Object invokeSuper = methodProxy.invokeSuper(o, objects); //增强 System.out.println("刮大白"); return invokeSuper; }); PersonService personService = (PersonService) enhancer.create(); personService.show(); //cglib动态代理会代理被代理类的所有方法 }}打印结果: 毛坯房 刮大白

事务管理

声明式事务

名称:@Transactional

  • 类型:方法注解,类注解,接口注解
  • 位置:方法定义上方,类定义上方,接口定义上方
  • 作用:设置当前类/接口中所有方法或具体方法开启事务,并指定相关事务属性
  • 范例
@Transactional(readOnly = false,	//是否只读事物timeout = -1,	//超时时间,-1为不超时isolation = Isolation.DEFAULT,	//隔离级别,默认是跟随数据库rollbackFor = {
ArithmeticException.class, IOException.class}, //抛出指定异常,回滚事物noRollbackFor = {
}, //抛出指定异常不会滚事物propagation = Propagation.REQUIRES_NEW //事物传播行为)

需要在spring开启事务注解驱动,并指定对应的事务管理器

*<tx:annotation-driven transaction-manager=“txManager”/>

转载地址:https://blog.csdn.net/drug1910951117/article/details/107508918 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:jackson.databind.exc.InvalidDefinitionException:NoSerializerFoundForClassCom.project.domain.Account
下一篇:关于spring配置文件中不能使用&的问题

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年04月13日 10时38分30秒