spring aop

约定编程:我们只需要实现约定的流程部分,而具体实现通过框架实现

“约定编程”(Convention Over Configuration)是一种软件开发的理念,旨在减少开发者在项目配置上的决策,并通过约定促进开发者之间的协作和项目的一致性。

aop的约定执行流程:
请添加图片描述

AOP的具体实现过程(由框架实现)

有三个重要的对象,一个是被代理的类,一个是拦截器,一个是代理对象。

public interface HelloService{
	public void sayHello(String name);
}
//被代理对象
public class HelloServiceImpl implements HelloService{
	@Override
	public void sayHello(String name){
		System.out.println("hello"+name);
	}
}
//拦截器接口
public interface Interceptor{
	public boolean before();
	public void after();
	public Object around(Invocation invocation);
	public void afterReturning();
	public void afterThrowing();
	boolean useAround();
}

执行被代理对象的方法的一个包装类
public class Invocation{
	private Object[] params;
	private Method method;
	private Object target;

	public Invocation(Object target,Method method,Object[] params){
		this.target=target;
		this.method=method;
		this.params=params;
	}
	
	public Object proceed(){
		return method.invoke(target,params);
	}
}
//拦截器的实现
public class MyInterceptor implements Interceptor{
	@Override
	public boolean before(){;}
	@Override
	public boolean useAround(){ return true;}
	@Override
	public void after(){;}
	@Override
	public void after(){;}
	@Override
	public Object around(Invocation invocation){
		System.out.println("around before...");
		Object obj=invocation.proceed();
		System.out.println("around after...");
		return obj;
	}
	@Override
	public void afterReturning(){;}
	@Override
	public void afterThrowing(){;}
}
//实现aop约定编程的具体类
public class ProxyBean implements InvocationHandler{
	private Object target=null;//被代理对象
	private Interceptor interceptor=null;//拦截器
	@Override
	public static Object getProxyBean(Object target,Interceptor interceptor){
		ProxyBean proxyBean = new ProxyBean();
		proxyBean.target = target;
		proxyBean.interceptor = interceptor;
		Object proxy=Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces().proxyBean);
		return proxy;//返回代理对象
	}
	@Override
	public Object invoke(Object proxy,Method method,Object[] args){
		boolean exceptionFlag = false;
		Invocation invocation = new Invocation(target,method,args);
		this.interceptor.before();
		Object retObj = null;
		if(this.interceptor.useAround()){
			retObj=this.interceptor.around(invocation);
		else
			retObj=method.invoke(target,args);
		return retObj;
	}

AOP

切点(Pointcut)在 AOP 中用于定义哪些连接点(Join Point)会被拦截器(Advice)所拦截。连接点是在程序执行过程中能够插入拦截器的点,比如方法调用、方法执行时异常抛出等。切点定义了一组连接点,这些连接点满足切点的条件,会被相应的拦截器所拦截。

所以,切点可以看作是一种匹配规则,它确定了哪些连接点会被织入(Weaving)到切面(Aspect)中。连接点是一个程序执行的具体位置,而切点则定义了应该在哪些具体位置执行拦截器中的逻辑。

切面(Aspect)

在 Spring 框架中,切面通常作为一个普通的 Java 类,并使用 @Aspect 注解进行标注。
在切面中,你可以定义一系列的通知(Advice)以及切点(Pointcut)。

通知(Advice)

通知是切面的具体行为。它定义了在程序执行的不同点上执行的代码。
Spring AOP 支持以下几种类型的通知:
前置通知(Before advice):在方法执行前执行。
后置通知(After returning advice):在方法执行后执行。
后置异常通知(After throwing advice):在方法抛出异常时执行。
后置最终通知(After finally advice):在方法执行后执行,无论方法是否抛出异常都会执行。
环绕通知(Around advice):在方法执行前后都执行,并且可以控制方法的执行。

切点(Pointcut):一个切面匹配的所有连接点都叫切点。

切点的主要功能就是简化连接点的定义和书写。
定义切点后,连接点想要织入切面,就将这个切面的连接点设置为切点,简化了开发。

可以只使用连接点而不使用切点。

切点定义了切面逻辑将被应用到哪些连接点(join points)上。
通过使用切点表达式(Pointcut expressions),可以精确地指定哪些方法、哪些类需要应用切面逻辑。

连接点(Join point)

连接点是在应用程序执行过程中可以插入切面的点,方法调用或异常抛出时。

引入(Introduction)

引入允许向现有类添加新方法或属性。在 Spring AOP 中,引入允许你向现有的类中添加新的接口实现。

目标对象(Target object)

目标对象是被代理的对象,它包含了切面逻辑所要应用的方法。

代理(Proxy)

代理是一个类,它包装了目标对象,并且可以截获对目标对象方法的调用,以便在调用前后执行切面逻辑。

织入(Weaving)

织入是将切面逻辑应用到目标对象的过程。织入可以在编译时、类加载时、运行时进行。

为什么要使用AOP?

减少重复工作,比如使用jdbc需要获得连接和statement,使用AOP可以简化这些过程。

定义切面

@Aspect
public class MyAspect{
	@Before("execution(*com.springboot.chapter4.aspect.service.impl.UserServiceImp.printUser(..))")//通过连接点接入
	public void befor(){}
	
	@After("execution(*com.springboot.chapter4.aspect.service.impl.UserServiceImp.printUser(..))")
	public void after(){}
	
	@AfterReturning("execution(*com.springboot.chapter4.aspect.service.impl.UserServiceImp.printUser(..))")
	public void returning(){}
	
	@AfterThrowing("execution(*com.springboot.chapter4.aspect.service.impl.UserServiceImp.printUser(..))")
	public void throwing(){}
}

定义切点

会使用excution()里的正则式去匹配使用切点的,为了简化开发,我们也可以在切面中定义一个切点,然后赋值给方法。

@Aspect
public class MyAspect{
	@Pointcut("execution(*com.springboot.chapter4.aspect.esrvice.impl.UserServiceImple.printUesr(..))")
	public void pointCut(){}
	
	@Before("pointCut()")//使用切点(定义了切点的方法名)作为通知的连接点
	public void before(){}
	
	@After("ponintCut()")
	public void after(){}
}

环绕通知

最强大的切面,不执行原方法,而是执行环绕通知的方法。

@Around("pointCut()")
public void around(ProceedingJoinPoint jp){
	System.out.println("around before..");
	jp.proceed();
	System.out.println("after..");
}

execution中的正则表达式

execution(*com.springboot.chapter4.aspect.service.impl.UserServiceImpl.printUser(…))
*表示返回类型,(…)表示可以进行任意参数匹配

相关推荐

  1. SpringAOP的实现原理

    2024-04-08 14:18:05       53 阅读
  2. 一个简易的SpringAOP实例

    2024-04-08 14:18:05       55 阅读
  3. 浅谈SpringAOP实现原理

    2024-04-08 14:18:05       44 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-08 14:18:05       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-08 14:18:05       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-08 14:18:05       87 阅读
  4. Python语言-面向对象

    2024-04-08 14:18:05       96 阅读

热门阅读

  1. (26)4.7 字符函数和字符串函数

    2024-04-08 14:18:05       31 阅读
  2. 网络空间安全攻防平台搭建

    2024-04-08 14:18:05       31 阅读
  3. 【QT教程】QT6 WebSocket编程

    2024-04-08 14:18:05       25 阅读
  4. uni-app嵌套webview监听事件

    2024-04-08 14:18:05       30 阅读
  5. Python爬虫学习(二):xpath解析html

    2024-04-08 14:18:05       35 阅读
  6. 如何防止SQL注入?能够采取什么措施?

    2024-04-08 14:18:05       34 阅读
  7. 计算机中,逻辑端口

    2024-04-08 14:18:05       48 阅读
  8. 2020 年 12 月青少年软编等考 C 语言一级真题解析

    2024-04-08 14:18:05       39 阅读
  9. 基于注解方式 Ioc配置

    2024-04-08 14:18:05       42 阅读