Spring AOP的基础相关知识

Spring AOP 相关知识的划分

  • Spring AOP的定义及相关名词
  • 类变成通知的几种方式及相关jar包
  • execution表达式
  • 基于实现接口方式的通知
    • 前置通知
    • 环绕通知
    • 异常通知
  • 基于注解方式的通知
    • 前置通知 and 环绕通知 and 异常通知
  • 基于schema配置方式的通知
    • 前置通知 and 环绕通知 and 异常通知

Spring AOP的定义及相关名词

AOP 面向切面编程 将一个方法add()【这个方法可以存在于多个对象中】定义为切入点,在执行这个方法时【可以在执行之前插入通知,执行之后插入通知】

Spring AOP的基础相关知识_第1张图片

类变成通知的几种方式及相关jar包

类——>通知 方式:

  1. 实现接口
  2. 注解
  3. 配置

编写通知所需要的jar包:

  1. aopaliance.jar
  2. aspectjweaver.jar

execution表达式

Spring AOP的基础相关知识_第2张图片

基于实现接口方式的通知

前置通知

  1. 首先编写通知类(前置通知实现接口MethodBeforeAdvice)
public class LogBefore implements MethodBeforeAdvice {

	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		System.out.println("前置通知——目标对象:"+target+"调用方法:"+method.getName()+"参数个数:"+args.length);
		
	}

}

  1. 编写业务类,业务方法:
	public void addstudent(Student student) {

	//	studentDao = null;//测试异常通知
		studentDao.addstudent(student);
	}

  1. 将通知类,业务类纳入IOC容器中,【在IOC容器中,配置AOP连接线】{定义切入点为一端,通知类为另一端,通过pointcut-ref将两端连接起来}

     
     <bean id="logBefore" class="org.motingyu.aop.LogBefore">bean>
     
     
     <aop:config>
     	
     	
     	<aop:pointcut expression=" execution(public void  org.motinyu.service.impl.StudentServiceImpl.addstudent(org.motinyu.entity.Student )) " id="poioncut"/>
     	
     	<aop:advisor advice-ref="logBefore" pointcut-ref="poioncut"/>
     aop:config>

环绕通知

环绕通知(实现接口MethodInterceptor)在目标方法的前后,异常发生时,最终等各个地方都可以进行的通知
【最强大的通知:可以获取目标方法的全部控制权(目标方法是否执行,执行之前,执行之后的参数,返回值等)】
在使用环绕通知时,目标方法的一切通知都可以通过invocation参数取得。
环绕通知底层是通过拦截器实现的。
  1. 首先编写通知类(环绕通知实现接口MethodInterceptor)
public class LogAround implements MethodInterceptor {
	 Object result = null;
	public Object invoke(MethodInvocation invocation) throws Throwable {
	
		try {
			System.out.println("用环绕通知实现的【前置通知】......:目标对象:"+invocation.getThis()+"调用方法:"+invocation.getMethod().getName());
			
			//invocation.proceed()之前的代码是前置通知
			 result	= invocation.proceed(); //控制着目标方法的执行,addStudent();
			//result 就是目标方法addStudent()的返回值;
			//invocation.proceed()之前的代码是后置通知
			
			System.out.println("用环绕通知实现的【后置通知】......");
			
		}catch(Exception e) {
			//异常通知
			System.out.println("用环绕通知实现的【异常通知】......");
		
		}
		return null;
	}

}

  1. 编写业务类,业务方法:(同上)
  2. 将通知类,业务类纳入IOC容器中,【在IOC容器中,配置AOP连接线】{定义切入点为一端,通知类为另一端,通过pointcut-ref将两端连接起来}(同上)

异常通知

异常通知 需要实现接口ThrowsAdvice (发生异常,触发通知)【实现同上】

根据异常通知接口的定义可以发现,异常通知的实现类必须编写以下方法
public void afterThrowing([Method, args, target], ThrowableSubclass) 
[]里的参数,要么都有,要么都没有

基于注解方式的通知

需要在配置文件中开启对AOP的支持

 
      <aop:aspectj-autoproxy>aop:aspectj-autoproxy>

需要注意的是:

@Component("logAnnotation")   // 类前  将该类纳入IOC容器中 别忘配置扫描器
@Aspect  //   类前  声明此类是一个通知类
@Before("execution()")  // 方法前加 :定义切入点  前置通知 获取目标参数  JoinPoint
@AfterReturning( pointcut ="execution()",returning= "")  //后置通知 添加返回值
@AfterThrowing( pointcut="execution()",throwing = "") //异常通知:如果只捕捉特定异常信息,则可以通过第二个参数实现:e
@Around("execution()") 	//环绕通知  获取目标信息使用 参数 ProceedingJoinPoint

基于注解方式的通知,应为通知类,业务类都在一个类中有联系,故不需要在配置文件中进行连接。

前置通知 and 环绕通知 and 异常通知

package org.motingyu.aop;

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.springframework.stereotype.Component;

@Component("logAnnotation")   //将该类纳入IOC容器中
@Aspect  //声明此类是一个通知类
public class LogAspectAnnotation {
	
	//前置通知
	@Before("execution(public *  org.motinyu.service.impl.StudentServiceImpl.addstudent(..))") //属性:定义切点
	public void myBefore() {
		
		System.out.println("<<注解形式——前置通知>>");
	}
	
	
	//后置通知 对象参数 使用JoinPoint  ,返回值 returningValue需要在注解中声明
	@AfterReturning( pointcut ="execution(public *  org.motinyu.service.impl.StudentServiceImpl.addstudent(..))",returning= "returningValue")
	public void myAfter(JoinPoint jp,Object returningValue) {
		
		System.out.println("<<注解形式——后置通知>>:目标对象:"+jp.getTarget()+"方法名:"+jp.getSignature().getName()+"参数列表个数:"+jp.getArgs().length+"返回值:"+returningValue);
	}
	
	//异常通知:如果只捕捉特定异常信息,则可以通过第二个参数实现:e
	@AfterThrowing( pointcut="execution(public *  org.motinyu.service.impl.StudentServiceImpl.addstudent(..))",throwing = "e")
	public void myException(JoinPoint jp,NullPointerException e) {//此异常只会捕捉NullPointerException这个类型的异常
		
		System.out.println("<<$$$注解形式——异常通知>>----------e:"+e.getMessage());
	}
	
	//环绕通知 对象参数与别个不一样 使用 ProceedingJoinPoint
	@Around("execution(public *  org.motinyu.service.impl.StudentServiceImpl.addstudent(..))")
	public void myAround(ProceedingJoinPoint jp) {
		//方法执行之前:前置通知
		
		try {
			//方法执行时
			jp.proceed();
			
			//方法执行之后:后置通知
			System.out.println("<<[环绕]注解形式——后置通知>>:");
		}catch(Throwable e) {
			//发生异常:异常通知
			System.out.println("<<[环绕]注解形式——异常通知>>:");
			
		}finally {
			//最终通知
			System.out.println("<<[环绕]注解形式——最终通知>>:");
		}
			
	}

	//最终通知
	@After("execution(public *  org.motinyu.service.impl.StudentServiceImpl.addstudent(..))")
	public void myAfter() {
		System.out.println("<<[myFter]注解形式——最终通知>>:");
		
	}
	
}

基于schema配置方式的通知

基于schema配置方式的通知,自己创建一个普通的类,在配置文件中,将此类配置成为通知类,并将通知类和业务类连接起来。

前置通知 and 环绕通知 and 异常通知

  1. 首先编写一个普通类,里面有自己写的通知方法:(添加到IOC容器中)
public class LogSchema {
	
   //前置通知
	public void myBefore() {
		System.out.println("###[Schema形式]-----前置通知");
		
	}
	
	//后置通知 返回值 returningValue需要在配置文件中声明
	public void myAfter(JoinPoint jp,Object returningValue) {		
		System.out.println("###[Schema形式]-----后置通知:目标对象:" +jp.getThis()+"目标方法:"+jp.getSignature().getName()+"参数个数:"+jp.getArgs().length+"返回值:"+returningValue);

	}
	
	//环绕通知 对象参数与别个不一样 使用 ProceedingJoinPoint
	public Object  myAround( ProceedingJoinPoint jp) {
		Object result = null;
		System.out.println("!!!!!###[Schema形式环绕通知]-----前置通知");
		try {
			result = jp.proceed();  //控制目标方法
		System.out.println("!!!!!###[Schema形式环绕通知]-----后置通知");		
		}catch(Throwable e) {
			
			System.out.println("!!!!!###[Schema形式环绕通知]-----异常通知");		
		}
		
		return result;
	}

	
	//异常通知 捕捉特定异常   参数e 需要在配置文件中声明
	 public void myException(NullPointerException e) {
			System.out.println("KKKKK###[Schema形式]-----异常通知:e" +e.getMessage());
	 }
}

  1. 在配置文件中,将刚才写的类配置为通知,并连接通知类与业务类:

    【注意】配置标签与基于实现接口方式的通知略微不同;

 <aop:config>
      	
     	<aop:pointcut expression=" execution(public *  org.motinyu.service.impl.StudentServiceImpl.addstudent(.. )) " id="pointschema"/>
     	
     	 <aop:aspect ref="logSchema">
      		<aop:before method="myBefore" pointcut-ref="pointschema"/>
      		<aop:after-returning method="myAfter" returning="returningValue"  pointcut-ref="pointschema"/>
     		<aop:around method="myAround" pointcut-ref="pointschema" />
     		<aop:after-throwing method="myException" pointcut-ref="pointschema" throwing="e"/>
     	 aop:aspect>
      aop:config>
     

你可能感兴趣的:(Spring,java,aop,spring)