Spring4实现AOP

AOP又称面向切面编程,可以不变改变原有业务的基础上进行功能的扩展,例如我们声明一个service类来处理servlet传过来的数据,每一次调用service中的验证登录信息方法的时候的都要进行日志的记录,在不改变该验证方法的基础上,我们可以利用AOP思想借助spring的提供的类,进行面向切面编程,将该方法当作切点,配置前置通知和后置通知。

一、需要的包
)
二、Schema-based实现方式
1、先声明一个类实现接口

  1. 前置通知实现MethodBeforeAdvice接口(所在包:org.springframework.aop.MethodBeforeAdvice)
  2. 后置通知实现AfterReturningAdvice接口(所在包:org.springframework.aop.AfterReturningAdvice)
  3. 实现接口的未实现方法2、实现接口中各方法的参数说明

2、实现接口中未实现的方法进行

public class MyBeforeAdvice implements MethodBeforeAdvice {
	@Override
	public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
		System.out.println("执行前置切面");		
	}
}

参数说明:

  1. arg0: 切点方法返回值
  2. arg1:切点方法对象
  3. arg2:切点方法参数
  4. arg3:切点方法所在类的对象

3、applicationContext.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"
	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="mybefor" class="com.hpu.tadvice.MyBeforeAdvice"></bean>
<!-- 通知类 -->
	<bean id="demo" class="com.hpu.test.Demo"></bean>
	<aop:config>
	   <aop:pointcut expression="execution(* com.hpu.test.Demo.demo2())" id="mypoint"/>
	   <aop:advisor advice-ref="mybefor" pointcut-ref="mypoint"/>
	</aop:config>
	
</beans>
  1. <aop:pointcut expression=“execution(* com.hpu.test.Demo.demo2())” id=“mypoint”/>配置切点
  2. <aop:advisor advice-ref=“mybefor” pointcut-ref=“mypoint”/>通知类配置
  3. 注意 * 通配符,匹配任意方法名,任意类名,任意一级包名
  4. 如果希望匹配任意方法参数 (…)

4、测试代码

package com.hpu.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("applicationContextl.xml");
	 Demo bean = ac.getBean("demo",Demo.class);
	 bean.demo1();
	 bean.demo2();
	 bean.demo3();
	}
}

三、AspectJ 方式实现
1、声明一个类不需要实现任何接口,可以在该类中重写前置通知方法或后置通知方法

package com.hpu.tadvice;

import org.aspectj.lang.ProceedingJoinPoint;

public class MyAdvice {
    public void mybefore(String name1,int age1){
      System.out.println("前置"+name1 );
    }
    public void mybefore1(String name1){
      System.out.println("前置:"+name1);
    }
    public void myaftering(){
      System.out.println("后置 2");
    }
    public void myafter(){
      System.out.println("后置 1");
    }
    public void mythrow(){
      System.out.println("异常");
    }
    public Object myarround(ProceedingJoinPoint p) throws
      Throwable{
        System.out.println("执行环绕");
        System.out.println("环绕-前置");
        Object result = p.proceed();
        System.out.println("环绕后置");
        return result;
    }
}

2、配置applicationContext

	<bean id="myadvice" class="com.hpu.tadvice.MyAdvice"></bean>
	<aop:config>
<!-- 	   <aop:pointcut expression="execution(* com.hpu.test.Demo.demo2())" id="mypoint"/>
	   <aop:advisor advice-ref="mybefor" pointcut-ref="mypoint"/> -->
	   
	   <aop:aspect ref="myadvice">
	      <aop:pointcut expression="execution(* com.hpu.test.Demo.demo1(String,int)) and args(name1,age1)" id="mypoint"/>
             <aop:before method="mybefore" pointcut-ref="mypoint" arg-names="name1,age1"/>
             <aop:after method="myafter" pointcut-ref="mypoint"  arg-names="name1,age1"/>   
	   </aop:aspect>
	</aop:config>

标签解释

<aop:after/> 后置通知,是否出现异常都执行
<aop:after-returing/> 后置通知,只有当切点正确执行时执行
<aop:after/> 和 <aop:after-returing/> 和<aop:after-throwing/>执行顺序和配置顺序有关
execution() 括号不能扩上 args
中间使用 and 不能使用&& 由 spring 把 and 解析成&&
args(名称) 名称自定义的.顺序和 demo1(参数,参数)对应
<aop:before/> arg-names=” 名 称 ” 名 称 来 源 于expression=”” 中 args(),名称必须一样
args() 有几个参数,arg-names 里面必须有几个参数
arg-names=”” 里面名称必须和通知方法参数名对应

四、环绕通知
1、声明一个类实现MethodInterceptor接口

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;
	}

}

2、applicationContext.xml

<bean id="myarround" class="com.bjsxt.advice.MyArround"></bean>
<aop:config>
      <aop:pointcut expression="execution(*com.bjsxt.test.Demo.demo1())" id="mypoint"/>
      <aop:advisor advice-ref="myarround" pointcut-ref="mypoint" />
</aop:config>
<bean id="demo" class="com.bjsxt.test.Demo"></bean>
posted @ 2019-01-18 16:22  HPUGIS  阅读(331)  评论(0编辑  收藏  举报