Spring学习(三)— AOP及其通知类型的实现(一)

一、AOP ( Aspect Oriented Programming ) 面向切面编程

常用概念
   原有功能: 切点, pointcut
   前置通知: 在切点之前执行的功能(在目标方法之前执行). before advice
   后置通知: 在切点之后执行的功能(在目标方法之后执行),after advice
   如果切点执行过程中出现异常,会触发异常通知.throws advice
   所有功能总称叫做切面.
   织入: 把切面嵌入到原有功能的过程叫做织入

      AOP技术利用一种称为“横切”的技术,剖解开封装的对象内部,将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度(参考:https://blog.csdn.net/yuexianchang/article/details/77018603)。举个栗子,在银行的取钱存钱的过程分别为:取钱:开始取钱-->登录验证-->...-->完成取钱   ;  存钱: 开始存钱-->登录验证-->...-->完成存钱。这两个步骤里有一个共同的行为,就是要进行用户登录校验。那我们可以把这个功能单独封装为一个验证模块,之后在设计银行系统的时候便不需要考虑这个方面,直接略过,后面哪一个步骤需要校验了,就调用这个模块,调用完之后再回到原来的流程中继续进行。

如下图,在程序原有纵向执行流程中,针对某一个或某一些方法添加通知(类似拦截器的作用一样),形成横切面过程就叫做面向切面编程。

二、AOP 实现方式

  • Schema-based

           每个通知都需要实现接口或类
           配置 spring 配置文件时在<aop:config>配置

  •   AspectJ

           每个通知不需要实现接口或类
           配置 spring 配置文件是在<aop:config>的子标签<aop:aspect>中配置

三、Schema-based实现

1、jar包

2、新建通知类:前置通知类和后置通知类

package com.wzg.advice;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class MyBeforeAdvice implements MethodBeforeAdvice{

	@Override
	public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
		System.out.println("前置通知信息:");
		System.out.println("切点方法对象"+arg0+",方法名"+arg0.getName());
		if(arg1!=null&&arg1.length>0) {
			System.out.println("切点方法参数"+arg1);
		}else {
			System.out.println("切点方法没有参数");
		}
		System.out.println("对象"+arg2);
	}
}
package com.wzg.advice;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

public class MyAfterAdvice implements AfterReturningAdvice{

	@Override
	public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
		System.out.println("后置通知信息");
		System.out.println("切点方法返回值:"+arg0);
		System.out.println("切点方法对象"+arg1+",方法名"+arg1.getName());
		if(arg1!=null&&arg2.length>0) {
			System.out.println("切点方法参数"+arg2);
		}else {
			System.out.println("切点方法没有参数");
		}
		System.out.println("对象"+arg3);
	}

}

3. 配置 spring 配置文件

首先要引入aop的命名空间,这里可以理解为模块,需要spring的那部分功能,就调用相关的模块,引入相应的文件。之后配置通知类的<bean>并配置切面。

<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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <bean id="demo" class="com.wzg.test.Demo"></bean>
    <!--  配置通知类的<bean>   -->
    <bean id="mybefore" class="com.wzg.advice.MyBeforeAdvice"></bean>
    <bean id="myafter" class="com.wzg.advice.MyAfterAdvice"></bean>
    <aop:config>
        <!-- * 通配符,匹配任意方法名,任意类名,任意一级包名.如果希望匹配任意方法参数 (..)    -->
    	<aop:pointcut expression="execution(* com.wzg.test.Demo.*(..))" id="mypoint"/>
    	<aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"/>
    	<aop:advisor advice-ref="myafter" pointcut-ref="mypoint"/>
    </aop:config>

</beans>

4.测试类

package com.wzg.test;

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

public class test {
	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		Demo demo = ac.getBean("demo", Demo.class);
		demo.demo1();
	}
}

四、环绕通知(Schema-based实现)

  环绕通知类

package com.wzg.advice;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

/**
 * 环绕通知
 * @author wang
 *
 */
public class MyArround implements MethodInterceptor{

	@Override
	public Object invoke(MethodInvocation arg0) throws Throwable {
		System.out.println("环绕--前置");
		Object result = arg0.proceed();//放行,调用切点方式
		System.out.println("环绕--后置");
		return result;
	}
	
}

spring配置文件

   <bean id="mythrow" class="com.wzg.advice.MyArround"></bean>
   <aop:config>
   	<aop:pointcut expression="execution(* com.wzg.test.Demo.demo1())" id="mypoint"/>
   	<aop:advisor advice-ref="mythrow" pointcut-ref="mypoint"/>
   </aop:config>

五、异常通知(Schema-based实现)

新建一个类实现 throwsAdvice 接口,必须自己写方法,且必须叫 afterThrowing。
有两种参数方式,必须是 1 个或 4 个,异常类型要与切点报的异常类型一致

public class MyThrow implements ThrowsAdvice{
// public void afterThrowing(Method m, Object[] args,Object target, Exception ex) {
//     System.out.println("执行异常通知");
//  }
   public void afterThrowing(Exception ex) throws Throwable {
       System.out.println("执行异常通过-schema-based 方式");
    }
}

spring配置文件

   <bean id="mythrow" class="com.wzg.advice.MyThrow"></bean>
   <aop:config>
   	<aop:pointcut expression="execution(* com.wzg.test.Demo.demo1())" id="mypoint"/>
   	<aop:advisor advice-ref="mythrow" pointcut-ref="mypoint"/>
   </aop:config>

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值