Spring_第四章【AspectJ的AOP】

1:什么是AspectJ的aop

AspectJ是一个(AOP)面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。spring2.0之后新增了对AspectJ的支持

AspectJ支持Java注解和xml配置

@Before 前置通知,相当于BeforeAdvie(用于权限验证)

@AfterReturning 后置通知,相当于AfterReturningAdvie (操作日志记录)

@Around环绕通知,相当于MethodInterceptor(事务开启关闭)

@AfterThrowing异常通知,相当于ThrowAdvie(用于权限验证)

@After 最终通知,跟finally类似(用于权限验证)

execution(<访问修饰符> <返回值类型> <方法名>(<参数>)<异常>)

execution(public **(..))

2:怎么使用AspectJ的aop

2.1基于AspectJ注解的方式实现AOP

目标类代码

package com.thit.aspectj1;

public class userdao {
	public	String add(){
		System.out.println("添加方法!");
		return "OMG!";
	}
	public	void select(){
		int i=0/0;
		System.out.println("查询方法!");
	}
	public	void update(){
		System.out.println("修改方法!");
	}
	public	String delete(){
		System.out.println("删除方法!");
		return "CNM";
	}
}

切面类代码:

package com.thit.aspectj1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.After;

/**
 * 
 * @author 79027 切面类
 */
@Aspect
public class aspectj {
	// 前置通知
	@Before("execution (* com.thit.aspectj1.userdao.ad*(..))")
	public void before(JoinPoint j) {
		System.out.println("前置通知" + j);
		// 前置通知execution(void com.thit.aspectj1.userdao.add())
	}

	// 后置通知,returning定义方法返回值
	@AfterReturning(value = "execution (* com.thit.aspectj1.userdao.add(..))", returning = "obj")
	public void After(Object obj) {
		System.out.println("后置通知");
		System.out.println("后置通知接受方法参数:" + obj);
	}

	// 环绕通知,returning定义方法返回值
	@Around(value = "execution (* com.thit.aspectj1.userdao.delete(..))")
	public Object Around(ProceedingJoinPoint joinPoint) {
		System.out.println("---环绕通知之前---");
		Object o = null;
		try {
			// 如果没有joinPoint.proceed,则目标方法不会执行
			o = joinPoint.proceed();
			System.out.println("目标方法返回值:" + o);
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} // 执行目标方法
		System.out.println("---环绕通知之后---");
		return o;
	}

	// 异常通知
	@AfterThrowing(value = "execution (* com.thit.aspectj1.userdao.select(..))", throwing = "excption")
	public void AfterThrowing(Throwable excption) {
		System.out.println("---异常通知---:" + excption);

	}

	// 最终通知
	@After(value = "execution (* com.thit.aspectj1.userdao.select(..))")
	public void After() {
		System.out.println("---最终无论是否有异常---");

	}
}

切面代码类优化

package com.thit.aspectj1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.After;

/**
 * 
 * @author 79027 切面类
 */
@Aspect
public class aspectj {
	// 前置通知
	@Before("p1()")
	public void before(JoinPoint j) {
		System.out.println("前置通知" + j);
		// 前置通知execution(void com.thit.aspectj1.userdao.add())
	}

	// 后置通知,returning定义方法返回值
	@AfterReturning(value = "p2()", returning = "obj")
	public void After(Object obj) {
		System.out.println("后置通知");
		System.out.println("后置通知接受方法参数:" + obj);
	}

	// 环绕通知,returning定义方法返回值
	@Around(value = "p3()")
	public Object Around(ProceedingJoinPoint joinPoint) {
		System.out.println("---环绕通知之前---");
		Object o = null;
		try {
			// 如果没有joinPoint.proceed,则目标方法不会执行
			o = joinPoint.proceed();
			System.out.println("目标方法返回值:" + o);
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} // 执行目标方法
		System.out.println("---环绕通知之后---");
		return o;
	}

	// 异常通知
	@AfterThrowing(value = "p4()", throwing = "excption")
	public void AfterThrowing(Throwable excption) {
		System.out.println("---异常通知---:" + excption);

	}

	// 最终通知
	@After(value = "p5()")
	public void After() {
		System.out.println("---最终无论是否有异常---");

	}
	//用于隔离大量额切点配置,随着代码增加只需要更改这两部分即可,便于维护
	@Pointcut("execution (* com.thit.aspectj1.userdao.ad*(..))")
	private void p1() {};
	@Pointcut(value = "execution (* com.thit.aspectj1.userdao.add(..))")
	private void p2() {};
	@Pointcut(value = "execution (* com.thit.aspectj1.userdao.delete(..))")
	private void p3() {};
	@Pointcut(value = "execution (* com.thit.aspectj1.userdao.delete(..))")
	private void p4() {};
	@Pointcut(value = "execution (* com.thit.aspectj1.userdao.select(..))")
	private void p5() {};
}

xml配置文件

<!--开启aspectJ的自动代理  -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!--目标类  -->
<bean id="userdao" class="com.thit.aspectj1.userdao"></bean>
<!--切面类-->
<bean  class="com.thit.aspectj1.aspectj"></bean>

测试方法:

	public void test1() {
	  ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
	  userdao u=(userdao) context.getBean("userdao");
	  u.add();
	  System.out.println("----------------------------------------------");
	  u.delete();
	  System.out.println("----------------------------------------------");
	  u.update();
	  System.out.println("----------------------------------------------");
	  u.select();
  }

输出结果:

----------------------------------------------
前置通知execution(String com.thit.aspectj1.userdao.add())
添加方法!
后置通知
后置通知接受方法参数:OMG!
----------------------------------------------
---环绕通知之前---
删除方法!
目标方法返回值:CNM
---环绕通知之后---
----------------------------------------------
修改方法!
----------------------------------------------
---最终无论是否有异常---
---异常通知---:java.lang.ArithmeticException: / by zero

2.2基于配置实现AspectJ的AOP

目标类代码

package com.thit.aspectj2xml;

public class userdao {
	public	String add(){
		System.out.println("添加方法!");
		return "OMG!";
	}
	public	void select(){
		int i=0/0;
		System.out.println("查询方法!");
	}
	public	void update(){
		System.out.println("修改方法!");
	}
	public	String delete(){
		System.out.println("删除方法!");
		return "CNM";
	}
}

切面类代码:

package com.thit.aspectj2xml;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.After;

/**
 * 
 * @author 79027 切面类
 */
@Aspect
public class aspectj {
	// 前置通知
	public void before(JoinPoint j) {
		System.out.println("前置通知" + j);
		// 前置通知execution(void com.thit.aspectj1.userdao.add())
	}

	// 后置通知,returning定义方法返回值
	public void Afterreturning(Object return1) {
		System.out.println("后置通知");
		System.out.println("后置通知接受方法参数:" + return1);
	}

	// 环绕通知,returning定义方法返回值
	public Object Around(ProceedingJoinPoint joinPoint) {
		System.out.println("---环绕通知之前---");
		Object o = null;
		try {
			// 如果没有joinPoint.proceed,则目标方法不会执行
			o = joinPoint.proceed();
			System.out.println("目标方法返回值:" + o);
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} // 执行目标方法
		System.out.println("---环绕通知之后---");
		return o;
	}

	// 异常通知
	public void AfterThrowing1(Throwable excption) {
		System.out.println("---异常通知---:" + excption);

	}

	// 最终通知
	public void After() {
		System.out.println("---最终无论是否有异常都会执行---");
	}
}

xml配置文件

<!--目标类 -->
	<bean id="userdao" class="com.thit.aspectj2xml.userdao"></bean>
	<!--切面类 -->
	<bean id="aspectj" class="com.thit.aspectj2xml.aspectj"></bean>
	<!-- AOP配置 -->
	<aop:config>
		<!--配置切入点                        execution (* com.thit.aspectj1.userdao.ad*(..)) -->
		<aop:pointcut expression="execution (* com.thit.aspectj2xml.userdao.add(..))" id="pointcut1" />
		<aop:pointcut expression="execution (* com.thit.aspectj2xml.userdao.ad*(..))" id="pointcut2" />
		<aop:pointcut expression="execution (* com.thit.aspectj2xml.userdao.delete(..))" id="pointcut3" />
		<aop:pointcut expression="execution (* com.thit.aspectj2xml.userdao.sel*(..))" id="pointcut4" />
		<aop:pointcut expression="execution (* com.thit.aspectj2xml.userdao.sel*(..))" id="pointcut5" />
		
		<!--配置切面 -->
		<aop:aspect ref="aspectj">
			<aop:before method="before" pointcut-ref="pointcut1"/>
		 	<aop:after-returning method="Afterreturning" pointcut-ref="pointcut2" returning="return1"/>
		    <aop:around method="Around" pointcut-ref="pointcut3" />
		    <aop:after-throwing method="AfterThrowing1" pointcut-ref="pointcut4" throwing = "excption"/>
		    <aop:after method="After" pointcut-ref="pointcut4"/> 
		</aop:aspect>
	</aop:config>

执行结果:

----------------------------------------------
前置通知execution(String com.thit.aspectj2xml.userdao.add())
添加方法!
后置通知
后置通知接受方法参数:OMG!
----------------------------------------------
---环绕通知之前---
删除方法!
目标方法返回值:CNM
---环绕通知之后---
----------------------------------------------
修改方法!
----------------------------------------------
---最终无论是否有异常都会执行---
---异常通知---:java.lang.ArithmeticException: / by zero

猜你喜欢

转载自blog.csdn.net/huyiju/article/details/81947774