前置通知、后置通知、异常通知和环绕通知

Spring配置通知需要的jar:aopaliance.jar和aspectjweaver.jar

前置通知
首先让一个类实现前置通知接口,并实现接口中的抽象方法

public class LogBefore implements MethodBeforeAdvice{

	//前置通知的具体内容
	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		System.out.println("前置通知");
	}
}

后置通知
实现后置通知接口,并实现方法

public class LogAfter implements AfterReturningAdvice{

	/*
	 * 参数含义
	 * target:执行切入点方法的对象,称为目标对象
	 * method:切入点方法名称
	 * args:切入点方法的参数
	 * returnValue:切入点方法的返回值类型
	 */
	@Override
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
		System.out.println("后置通知");
	}
}

异常通知
根据异常通知接口的定义可以发现,异常通知的实现类必须编写以下方法:
public void afterThrowing(Method , args,target,Throwable ex);

public class LogException implements ThrowsAdvice{

	//异常通知类的具体方法
	public void afterThrowing(Method method,Object[] args,Object target,Throwable ex) {
		//参数意义和后置通知相似
		System.out.println("异常通知");
	}
}

环绕通知
在目标方法的前后、异常发生时、最终等各个地方都可以进行通知,最强大的一种通知,可以获取目标方法的全部控制权(目标方法是否执行、执行前后、参数、返回值等)。在使用环绕通知时,目标方法的一切信息都可以通过invocation参数获取到。
环绕通知底层是通过拦截器实现的。

public class LogAround implements MethodInterceptor{

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		
		Object result = null;
		//方法体1
		try {
			//方法体2
			System.out.println("用环绕通知实现的前置通知");
			
			//invocation.proceed()之前的代码是前置通知
			result = invocation.proceed();//控制着目标方法,addStudent()是否执行。result是方法的返回值
			//result就是目标方法addStudent()方法的返回值
			//invocation.proceed()后面的代码是后置通知
			System.out.println("用环绕通知实现的后置通知");
			
			/*
			 * 通过invocation获取之前后置通知的参数
			 * 获取目标对象target:invocation.getThis()
			 * 获取方法名:invocation.getMethod().getName()
			 * 获取方法参数个数:invocation.getArguments().length
			 * 
			 */
		}catch(Exception e) {
			//方法体3
			//异常通知
			System.out.println("用环绕通知实现的异常通知");
		}
		return result;
	}
}

然后在配置文件中进行相应的配置

<bean id="studentService" class="org.yao.service.StudentServiceImpl">
		<property name="studentDao" ref="studentDao"></property>
	</bean>
	
	<!-- 配置前置通知 -->
	<bean id="logbefore" class="org.yao.aop.LogBefore"></bean>
	
	<!--addStudent()和通知进行关联 -->
	<aop:config>
		<!-- 配置切入点(在哪里执行通知),业务类的具体方法 -->
		<aop:pointcut expression="execution(public void org.yao.service.StudentServiceImpl.delStudentByNo(int)) or execution(public void org.yao.service.StudentServiceImpl.addStudent(org.yao.entity.Student))" id="pointcut"/>
		<!-- advisor相当于连接切入点和切入面的线 -->
		<aop:advisor advice-ref="logbefore" pointcut-ref="pointcut"/>
	</aop:config>
	
	<!-- 配置后置通知 -->
	<aop:config>
		<aop:pointcut expression="execution(public void org.yao.service.StudentServiceImpl.addStudent(org.yao.entity.Student)" id="pointcut2"/>
		<aop:advisor advice-ref="logAfter" pointcut-ref="pointcut2"/>
	</aop:config>
	
	<bean id="logAfter" class="org.yao.aop.LogAfter"></bean>
	
	<!-- 配置异常通知 -->
	<bean id="logException" class="org.yao.aop.LogException"></bean>
	
	<aop:config>
		<aop:pointcut expression="execution(public void org.yao.service.StudentServiceImpl.addStudent(org.yao.entity.Student)" id="piontcut3"/>
		<aop:advisor advice-ref="logException" pointcut-ref="piontcut3"/>
	</aop:config>
	
	<!-- 配置环绕通知 -->
	<bean id="logAround" class="org.yao.aop.LogAround"></bean>
	
	<aop:config>
		<aop:pointcut expression="execution(public void org.yao.service.StudentServiceImpl.addStudent(org.yao.entity.Student)" id="pointcut4"/>
		<aop:advisor advice-ref="logAround" pointcut-ref="pointcut4"/>
	</aop:config>

如果在测试时出现了类似:java.lang.NoClassDefoundError:org/apache/commons/pool/impl/GenericObjectPool的异常,说明缺少jar


版权声明:本文为m0_46163291原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。