关于spring中切面编程 aop的解析

spring中aop中的两种方式

第一种方式:注解的方式

第一步:创建aspect类

package com.liusir.aop.xml;

import java.util.Arrays;
import java.util.List;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

public class longingaspect {

	public void declareJoinPointExpression() {}
	
	public void BeforeMethod(JoinPoint joinpoint) {
		String methodname = joinpoint.getSignature().getName();
		List<Object> args = Arrays.asList(joinpoint.getArgs());
		System.out.println("The method" + methodname + "begins with" + args);
	}


	public void afterMethod(JoinPoint joinpoint) {
		String methodname = joinpoint.getSignature().getName();
		System.out.println("The method" + methodname + "end..");
	}

	public void afterReturnMethod(JoinPoint joinpoint, Object result) {
		String methodname = joinpoint.getSignature().getName();
		System.out.println("The method" + methodname + "end.." + result);
	}
	public void throwingMethod(JoinPoint joinpoint, Exception ex) {
		String methodname = joinpoint.getSignature().getName();
		System.out.println("The method" + methodname + "end.." + ex);
	}
}

第二步:配置spring.xml文件

<!-- aop 自动切面编程 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

注解的方式文件的配置很简单。

第三步:加入相应的注解

一共有五种注解:@Before @After @AfterReturning @AfterThrowing @Round

注意:再注解当中需要备好 execution

下面是将上面的aspect代码进行完善

package com.liusir.aop;

import java.util.Arrays;
import java.util.List;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class longingaspect {

	//定义一个方法,用于表明切入点的表达式,一般的,该方法种不再添加任何代码
	//使用@Pointcut 来表明切入点的表达式
	//后面的其他通知直接使用方法名来引用当前的切入点的表达式
	@Pointcut("execution(int com.liusir.aop.ArithmeticDao.*(int, int))")
	public void declareJoinPointExpression() {}
	
    //用order来指定优先级, order值越小,优先级越高。
	@Order
	// 在目标方法执行前进行通知
	@Before("declareJoinPointExpression()")
	public void BeforeMethod(JoinPoint joinpoint) {
		String methodname = joinpoint.getSignature().getName();
		List<Object> args = Arrays.asList(joinpoint.getArgs());
		System.out.println("The method" + methodname + "begins with" + args);
	}

	// 在目标方法执行后进行通知,(无论是否发生异常都会通知)
	// 但是还不能访问结果
	@After("declareJoinPointExpression()")
	public void afterMethod(JoinPoint joinpoint) {
		String methodname = joinpoint.getSignature().getName();
		System.out.println("The method" + methodname + "end..");
	}

	// 在方法正常结束受执行的代码
	// 后置返回通知会有返回结果
	@AfterReturning(value = "declareJoinPointExpression()", returning = "result")
	public void afterReturnMethod(JoinPoint joinpoint, Object result) {
		String methodname = joinpoint.getSignature().getName();
		System.out.println("The method" + methodname + "end.." + result);
	}
	// 在目标受到异常时执行的代码
	// 可以访问异常对象,且可以指定出现特定异常时在执行通知的代码。
	@AfterThrowing(value = "declareJoinPointExpression()", throwing = "ex")
	public void throwingMethod(JoinPoint joinpoint, Exception ex) {
		String methodname = joinpoint.getSignature().getName();
		System.out.println("The method" + methodname + "end.." + ex);
	}
	// 环绕通知需要携带ProceedingJoinPoint这个
	// 环绕通知类似于动态代理的全过程:ProceedingJoinpoint的类型参数 可以指定是否执行目标方法
	// 且必须有返回值,返回值即为目标方法的返回值
	/*
	@Around("execution(int com.liusir.aop.ArithmeticDao.*(int, int))")
	public Object Around(ProceedingJoinPoint joinpoint) {
		Object object = null;
		try {
            //前置通知
			String methodname = joinpoint.getSignature().getName();
			System.out.println("The method" + methodname + "starts"+Arrays.asList(joinpoint.getArgs()) );
			//执行方法
			object = joinpoint.proceed();
			//后置通知返回值
			System.out.println("The method" + methodname + "end.."+object);
		} catch (Throwable e) {
			System.out.println("The method.."+e);
		}
		
		//后置通知。。
		System.out.println("The method end....");

		return object;
	}*/

}

注意: 里面有 点需要说:

第一点:切入点的表达式
@Pointcut(“execution(int com.liusir.aop.ArithmeticDao.*(int, int))”)
public void declareJoinPointExpression() {}
:一般这个方法内部是需要添加任何代码,只是一种标识作用。
:@Pointcut来标识
:例子:普通和使用表达式的差别
:切入点表达式:
	@AfterReturning(value = "declareJoinPointExpression()", returning = "result")
	  public void afterReturnMethod(JoinPoint joinpoint, Object result) {
		String methodname = joinpoint.getSignature().getName();
		System.out.println("The method" + methodname + "end.." + result);
	}
:普通:
	@AfterReturning(value ="execution(int com.liusir.aop.ArithmeticDao.*(int, int))" , returning = "result")
	public void afterReturnMethod(JoinPoint joinpoint, Object result) {
		String methodname = joinpoint.getSignature().getName();
		System.out.println("The method" + methodname + "end.." + result);
	}
第二点:@AfterReturning @AfterThrowing
注意AfterReturning注解里的内容,多一个returning,returning=“result”
是方法中的参数的名:public void afterreturnTest(JoinPoint joinpoint,Object result);
注意AfterThrowing注解里的内容,多了一个throwing,throwing=“ex”
是方法中异常的参数名:public void throwingMethod(JoinPoint joinpoint, Exception ex);
第三点:@around:
可以理解为将前面的四个注解组合起来,完全像动态代理的处理方式。
第四点:@Aspect

在这里插入图片描述

第五点:关于方法标签

在这里插入图片描述

在这里插入图片描述

如果大家想测试:下面将全部的代码

package com.liusir.aop;

public interface ArithmeticDao {
	public int add(int i,int j);
	public int div(int i,int j);

}
package com.liusir.aop;

import org.springframework.stereotype.Component;

@Component
public class ArithmeticImpl implements ArithmeticDao{
	
	@Override
	public  int add(int i,int j) {

		int result=i+j;
		return result;
	}

	@Override
	public int div(int i,int j) {

		int result=i/j;
		return result;
				
	}

}
package com.liusir.aop;

import java.util.Arrays;
import java.util.List;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class longingaspect {

	//定义一个方法,用于表明切入点的表达式,一般的,该方法种不再添加任何代码
	//使用@Pointcut 来表明切入点的表达式
	//后面的其他通知直接使用方法名来引用当前的切入点的表达式
	@Pointcut("execution(int com.liusir.aop.ArithmeticDao.*(int, int))")
	public void declareJoinPointExpression() {}
	
    //用order来指定优先级, order值越小,优先级越高。
	@Order
	// 在目标方法执行前进行通知
	@Before("declareJoinPointExpression()")
	public void BeforeMethod(JoinPoint joinpoint) {
		String methodname = joinpoint.getSignature().getName();
		List<Object> args = Arrays.asList(joinpoint.getArgs());
		System.out.println("The method" + methodname + "begins with" + args);
	}

	// 在目标方法执行后进行通知,(无论是否发生异常都会通知)
	// 但是还不能访问结果
	@After("declareJoinPointExpression()")
	public void afterMethod(JoinPoint joinpoint) {
		String methodname = joinpoint.getSignature().getName();
		System.out.println("The method" + methodname + "end..");
	}

	// 在方法正常结束受执行的代码
	// 后置返回通知会有返回结果
	@AfterReturning(value = "declareJoinPointExpression()", returning = "result")
	public void afterReturnMethod(JoinPoint joinpoint, Object result) {
		String methodname = joinpoint.getSignature().getName();
		System.out.println("The method" + methodname + "end.." + result);
	}
	// 在目标受到异常时执行的代码
	// 可以访问异常对象,且可以指定出现特定异常时在执行通知的代码。
	@AfterThrowing(value = "declareJoinPointExpression()", throwing = "ex")
	public void throwingMethod(JoinPoint joinpoint, Exception ex) {
		String methodname = joinpoint.getSignature().getName();
		System.out.println("The method" + methodname + "end.." + ex);
	}
	// 环绕通知需要携带ProceedingJoinPoint这个
	// 环绕通知类似于动态代理的全过程:ProceedingJoinpoint的类型参数 可以指定是否执行目标方法
	// 且必须有返回值,返回值即为目标方法的返回值
	/*
	@Around("execution(int com.liusir.aop.ArithmeticDao.*(int, int))")
	public Object Around(ProceedingJoinPoint joinpoint) {
		Object object = null;
		try {
            //前置通知
			String methodname = joinpoint.getSignature().getName();
			System.out.println("The method" + methodname + "starts"+Arrays.asList(joinpoint.getArgs()) );
			//执行方法
			object = joinpoint.proceed();
			//后置通知返回值
			System.out.println("The method" + methodname + "end.."+object);
		} catch (Throwable e) {
			System.out.println("The method.."+e);
		}
		
		//后置通知。。
		System.out.println("The method end....");

		return object;
	}*/
	
	
	

}
package com.liusir.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class main {

	

	public static void main(String[] args) {
		ApplicationContext ctx=null;
		ctx = new ClassPathXmlApplicationContext("aop.xml");
		ArithmeticDao arithmeticDao=ctx.getBean(ArithmeticDao.class);
		int add = arithmeticDao.add(2, 4);
		int div =arithmeticDao.div(2, 1);
		System.out.println(add);
	
	}
}

配置文件:
	<?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:aop="http://www.springframework.org/schema/aop"
	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/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">


<context:component-scan base-package="com.liusir.aop"></context:component-scan>


<!-- aop 自动切面编程 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>


</beans>

第二种方式:用spring.xml文件来配置

注意 :一下代码是上面代码将注解的部分全部删除,然后可以直接进行测试

spring.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:aop="http://www.springframework.org/schema/aop"
	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/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">

	<bean id="Arithmeticlmpl"
		class="com.liusir.aop.xml.ArithmeticImpl">
	</bean>
	<!-- 配置切面的bean -->
	<bean id="loggingaspect" class="com.liusir.aop.xml.longingaspect">
	</bean>

	<!-- 配置aop -->
	<aop:config>
		<!-- 配置切面表达式 -->
		<!-- 来定位那个类中方法信息。 -->
		<aop:pointcut
			expression="execution(int com.liusir.aop.xml.ArithmeticDao.*(int, int))"
			id="pointcut" />
		<!-- 切面表达式及通知 -->
		<aop:aspect ref="loggingaspect">
			<aop:before method="BeforeMethod" pointcut-ref="pointcut" />
			<aop:after-returning method="afterReturnMethod"
				pointcut-ref="pointcut" returning="result"/>
			<aop:after method="afterMethod" pointcut-ref="pointcut" />
			<aop:after-throwing method="throwingMethod" pointcut-ref="pointcut" throwing="ex"/>
		</aop:aspect>
	</aop:config>



</beans>

注意:第一点:

声明切面的代码实例

<!-- 配置切面的bean -->
	<bean id="loggingaspect" class="com.liusir.aop.xml.longingaspect">
	</bean>
	

在这里插入图片描述
在这里插入图片描述

声明切入点:

	<!-- 配置切面表达式 -->
		<!-- 来定位那个类中方法信息。 -->
		<aop:pointcut
			expression="execution(int com.liusir.aop.xml.ArithmeticDao.*(int, int))"
			id="pointcut" />

声明通知实例

<!-- 切面表达式及通知 -->
		<aop:aspect ref="loggingaspect">
			<aop:before method="BeforeMethod" pointcut-ref="pointcut" />
			<aop:after-returning method="afterReturnMethod"
				pointcut-ref="pointcut" returning="result"/>
			<aop:after method="afterMethod" pointcut-ref="pointcut" />
			<aop:after-throwing method="throwingMethod" pointcut-ref="pointcut" throwing="ex"/>
		</aop:aspect>

结合上面代码一起参考。

有什么问题可以留言哦! 😄😄

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值