欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring实战学习笔记整理(4)-AOP(面向切面编程)

程序员文章站 2024-02-15 12:09:28
...

AOP与OOP概念

OOP(Object Oriented Programming,面向对象编程),通过封装、继承将程序抽象为各个层次的对象,进而组合为模块或者程序,达到了软件工程中的重用性、灵活性、扩展性。程序的运行笼统地可以看为各层次对象之间的相互调用。
AOP(Aspect Oriented Programming,面向切面编程),将程序运行过程分解为一个个的切面,对特定的切面(某个步骤或者阶段)进行提取,达到解耦各种不同逻辑代码。
OOP是在程序分块层面上进行考虑,而AOP则是在程序运行的切面上进行考虑。

AOP使用

xml的使用方式

1.使用步骤
	(1)环境搭建,注意:导入aspectjweaver-1.9.5.jar
	(2)创建业务类、切面类
	(3)创建配置文件,并配置切面信息:以上涉及到的类必须纳入到Spring IOC容器管理
	(4)测试
2.记忆的点
	2.1切点的声明:标签、表达式
	2.2通知:前置通知、后置通知、返回通知、异常通知、环绕通知(!joinPoint.proceed())

注解的使用方式

1.使用步骤
	(1)环境搭建,注意:导入aspectjweaver-1.9.5.jar
	(2)创建业务类、切面类(定义了切面所有的东西)
	(3)开启包扫描、开启切面编程
	(4)测试
2.记忆的点
	2.1切点的声明:注解、表达式、声明在方法上
	2.2通知:前置通知、后置通知、返回通知、异常通知、环绕通知(!joinPoint.proceed())
	2.3切面类中@Aspect必须写

疫情足迹举例:

使用自我扫码进入形式和神奇设备负责记录形式两种形式,如图所示:
Spring实战学习笔记整理(4)-AOP(面向切面编程)

自我扫码进入形式

代码部分:

Person.java

/**
 * Person类,用于演示疫情足迹登录
 * @author Katrina
 *
 */
public class Person {

	/**
	 * 回家
	 */
	public void goHome() {
		System.out.println("回家扫码登记...");
		System.out.println("回家了");
		System.out.println("离家扫码登记...");
	}
	
	/**
	 * 去商场购物生活必需品
	 */
	public void goMarket() {
		System.out.println("去商场扫码登记...");
		System.out.println("去商场购买生活必需品");
		System.out.println("离开商场扫码登记...");
	}
	
	/**
	 * 去工作
	 */
	public void goWork() {
		System.out.println("去工作扫码登记...");
		System.out.println("去工作");
		System.out.println("离开扫码登记...");
	}
	
}

PersonTest.java

/**
 * 测试类,用于演示疫情足迹记录
 * @author Katrina
 *
 */
import org.junit.Test;
public class PersonTest {

	/**
	 * 测试非AOP疫情登记
	 */
	@Test
	public void test1() {
		Person person = new Person();
		person.goHome();
		person.goWork();
		person.goMarket();
	}
	
}
效果图:

Spring实战学习笔记整理(4)-AOP(面向切面编程)

神奇设备负责记录形式【xml形式配置AOP】

引入aspectjweaver-1.9.5.jarjar包
Spring实战学习笔记整理(4)-AOP(面向切面编程)

代码部分:

part1:

AOPPerson.java
/**
 * AOPPerson类,用于演示AOP
 * @author Katrina
 *
 */
public class AOPPerson {

	/**
	 * 回家方法
	 */
	public void goHome() {
		System.out.println("回家了");
	}
	
	/**
	 * 去商场方法
	 */
	public void goMarket(String markerName) {
		System.out.println("去商场");
	}
	
	/**
	 * 去工作方法
	 */
	public void goWork() {
		System.out.println("去工作");
	}
	
}
SuperMachine.java
/**
 * 超级机器,用于定义通知
 * @author Katrina
 *
 */
public class SuperMachine {

	/**
	 * 进入前(方法执行前)进行登记信息
	 */
	public void beforeIn() {
		System.out.println("进入前登记信息...");
	}
	
	/**
	 * 离开前(方法执行之后)进行登记信息
	 */
	public void beforeOut() {
		System.out.println("离开之前登记信息...");
	}
	
}
config.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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

	<!-- 注入类 -->
	<bean id="AOPPerson" class="demo.AOPPerson"></bean>
	<bean id="superMachine" class="demo.SuperMachine"></bean>

	<!-- AOP配置 -->
	<aop:config>
		<!-- 切面配置 -->
		<aop:aspect ref="superMachine">
			<!-- 
				定义切点:
				1.execution(执行): 
				2.表达式:execution(public * demo.AOPPerson.goHome(..) -> public void goHome() {
				表达式就是方法的描述:【访问修饰符 返回值 方法的全路径(参数列表)】
				通配符:*(全部)、..(0个或者多个)
			-->
			<!-- <aop:pointcut expression="execution(public void demo.AOPPerson.goHome())" id="pointCut"/> -->
			<!-- <aop:pointcut expression="execution(public void demo.AOPPerson.*())" id="pointCut"/> -->
			<!-- <aop:pointcut expression="execution(public void demo.AOPPerson.*(..))" id="pointCut"/> -->
			<aop:pointcut expression="execution(public * demo.AOPPerson.*(..))" id="pointCut"/>
			
			<!-- 注意:必须需要ref关联 -->
			<!-- 前置通知:执行方法之前执行 -->
			<aop:before method="beforeIn" pointcut-ref="pointCut"/>
			
			<!-- 后置通知:执行方法之后执行 -->
			<aop:after method="beforeOut" pointcut-ref="pointCut"/>
		</aop:aspect>
		
	</aop:config>
</beans>
AOPPersonTest.java
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * aop方式测试类
 * @author Katrina
 *
 */
public class AOPPersonTest {

	private ClassPathXmlApplicationContext context;

	@Before
	public void before() {
		context = new ClassPathXmlApplicationContext("config.xml");
	}
	
	/**
	 * aop的demo
	 */
	@Test
	public void test1() {
		AOPPerson person = context.getBean(AOPPerson.class);
		person.goHome();
		person.goMarket("万达超市");
		person.goWork();
	}
	
	@After
	public void after() {
		context.close();
	}
	
}
效果图:

Spring实战学习笔记整理(4)-AOP(面向切面编程)

part2:

SuperMachine.java
/**
 * 超级机器,用于定义通知
 * @author Katrina
 *
 */
public class SuperMachine {

	/**
	 * 进入前(方法执行前)进行登记信息
	 */
	public void beforeIn() {
		System.out.println("进入前登记信息...");
	}
	
	/**
	 * 离开前(方法执行之后)进行登记信息
	 */
	public void beforeOut() {
		System.out.println("离开之前登记信息...");
	}
	
	/**
	 * 返回通知
	 */
	public void returnMethod() {
		System.out.println("返回通知执行了...");
	}
	
}
config.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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

	<!-- 注入类 -->
	<bean id="AOPPerson" class="demo.AOPPerson"></bean>
	<bean id="superMachine" class="demo.SuperMachine"></bean>

	<!-- AOP配置 -->
	<aop:config>
		<!-- 切面配置 -->
		<aop:aspect ref="superMachine">
			<!-- 
				定义切点:
				1.execution(执行): 
				2.表达式:execution(public * demo.AOPPerson.goHome(..) -> public void goHome() {
				表达式就是方法的描述:【访问修饰符 返回值 方法的全路径(参数列表)】
				通配符:*(全部)、..(0个或者多个)
			-->
			<!-- <aop:pointcut expression="execution(public void demo.AOPPerson.goHome())" id="pointCut"/> -->
			<!-- <aop:pointcut expression="execution(public void demo.AOPPerson.*())" id="pointCut"/> -->
			<!-- <aop:pointcut expression="execution(public void demo.AOPPerson.*(..))" id="pointCut"/> -->
			<aop:pointcut expression="execution(public * demo.AOPPerson.*(..))" id="pointCut"/>
			
			<!-- 注意:必须需要ref关联 -->
			<!-- 前置通知:执行方法之前执行 -->
			<aop:before method="beforeIn" pointcut-ref="pointCut"/>
			<!-- 后置通知:执行方法之后执行 -->
			<aop:after method="beforeOut" pointcut-ref="pointCut"/>
			<!-- 返回通知:方法成功执行之后执行 -->
			<aop:after-returning method="returnMethod" pointcut-ref="pointCut"/>
		</aop:aspect>	
	</aop:config>
</beans>
效果图:

不对test进行修改,效果如图所示:
Spring实战学习笔记整理(4)-AOP(面向切面编程)
其他情况,若修改回家方法(添加参数),且在赋值的时候有误,则效果如图所示:
Spring实战学习笔记整理(4)-AOP(面向切面编程)
Spring实战学习笔记整理(4)-AOP(面向切面编程)
Spring实战学习笔记整理(4)-AOP(面向切面编程)

part3:

SuperMachine.java
/**
 * 超级机器,用于定义通知
 * @author Katrina
 *
 */
public class SuperMachine {

	/**
	 * 进入前(方法执行前)进行登记信息
	 */
	public void beforeIn() {
		System.out.println("进入前登记信息...");
	}
	
	/**
	 * 离开前(方法执行之后)进行登记信息
	 */
	public void beforeOut() {
		System.out.println("离开之前登记信息...");
	}
	
	/**
	 * 返回通知
	 */
	public void returnMethod() {
		System.out.println("返回通知执行了...");
	}
	
	/**
	 * 异常通知
	 */
	public void afterThrowing() {
		System.out.println("出现异常了...");
	}
	
}
config.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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

	<!-- 注入类 -->
	<bean id="AOPPerson" class="demo.AOPPerson"></bean>
	<bean id="superMachine" class="demo.SuperMachine"></bean>

	<!-- AOP配置 -->
	<aop:config>
		<!-- 切面配置 -->
		<aop:aspect ref="superMachine">
			<!-- 
				定义切点:
				1.execution(执行): 
				2.表达式:execution(public * demo.AOPPerson.goHome(..) -> public void goHome() {
				表达式就是方法的描述:【访问修饰符 返回值 方法的全路径(参数列表)】
				通配符:*(全部)、..(0个或者多个)
			-->
			<!-- <aop:pointcut expression="execution(public void demo.AOPPerson.goHome())" id="pointCut"/> -->
			<!-- <aop:pointcut expression="execution(public void demo.AOPPerson.*())" id="pointCut"/> -->
			<!-- <aop:pointcut expression="execution(public void demo.AOPPerson.*(..))" id="pointCut"/> -->
			<aop:pointcut expression="execution(public * demo.AOPPerson.*(..))" id="pointCut"/>
			
			<!-- 注意:必须需要ref关联 -->
			<!-- 前置通知:执行方法之前执行 -->
			<aop:before method="beforeIn" pointcut-ref="pointCut"/>
			<!-- 后置通知:执行方法之后执行 -->
			<aop:after method="beforeOut" pointcut-ref="pointCut"/>
			<!-- 返回通知:方法成功执行之后执行 -->
			<aop:after-returning method="returnMethod" pointcut-ref="pointCut"/>
			<!-- 异常通知:方法出现异常后执行 -->
			<aop:after-throwing method="afterThrowing" pointcut-ref="pointCut"/>
		</aop:aspect>
	</aop:config>
</beans>
效果图:

情况一,在测试类中修改代码为:person.goHome("123abc");,效果如图所示:
Spring实战学习笔记整理(4)-AOP(面向切面编程)
情况二,在测试类中修改代码为:person.goHome("123");,效果如图所示:
Spring实战学习笔记整理(4)-AOP(面向切面编程)

part4:

SuperMachine.java
import org.aspectj.lang.ProceedingJoinPoint;
/**
 * 超级机器,用于定义通知
 * @author Katrina
 *
 */
public class SuperMachine {

	/**
	 * 环绕通知
	 * @param joinPoint,一定要调用proceed方法
	 */
	public void around(ProceedingJoinPoint joinPoint) {
		System.out.println("进入前进行登记信息");
		
		boolean hasError = false;
		try {
			joinPoint.proceed(); //执行业务方法 
		} catch (Throwable e) {
			e.printStackTrace();
			System.out.println("出现异常了...");
			hasError = true;
		} 
		if (hasError) {
			System.out.println("出现异常信息");
		} else {
			System.out.println("成功返回值信息");
		}
		System.out.println("离开前进行登记信息");
	}
	
	/**
	 * 进入前(方法执行前)进行登记信息
	 */
	public void beforeIn() {
		System.out.println("进入前登记信息...");
	}
	
	/**
	 * 离开前(方法执行之后)进行登记信息
	 */
	public void beforeOut() {
		System.out.println("离开之前登记信息...");
	}
	
	/**
	 * 返回通知
	 */
	public void returnMethod() {
		System.out.println("返回通知执行了...");
	}
	
	/**
	 * 异常通知
	 */
	public void afterThrowing() {
		System.out.println("出现异常了...");
	}
	
}
config.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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

	<!-- 注入类 -->
	<bean id="AOPPerson" class="demo.AOPPerson"></bean>
	<bean id="superMachine" class="demo.SuperMachine"></bean>

	<!-- AOP配置 -->
	<aop:config>
		<!-- 切面配置 -->
		<aop:aspect ref="superMachine">
			<!-- 
				定义切点:
				1.execution(执行): 
				2.表达式:execution(public * demo.AOPPerson.goHome(..) -> public void goHome() {
				表达式就是方法的描述:【访问修饰符 返回值 方法的全路径(参数列表)】
				通配符:*(全部)、..(0个或者多个)
			-->
			<!-- <aop:pointcut expression="execution(public void demo.AOPPerson.goHome())" id="pointCut"/> -->
			<!-- <aop:pointcut expression="execution(public void demo.AOPPerson.*())" id="pointCut"/> -->
			<!-- <aop:pointcut expression="execution(public void demo.AOPPerson.*(..))" id="pointCut"/> -->
			<aop:pointcut expression="execution(public * demo.AOPPerson.*(..))" id="pointCut"/>
			
			<!-- 注意:必须需要ref关联 -->
			<!-- 前置通知:执行方法之前执行 -->
			<!-- <aop:before method="beforeIn" pointcut-ref="pointCut"/> -->
			<!-- 后置通知:执行方法之后执行 -->
			<!-- <aop:after method="beforeOut" pointcut-ref="pointCut"/> -->
			<!-- 返回通知:方法成功执行之后执行 -->
			<!-- <aop:after-returning method="returnMethod" pointcut-ref="pointCut"/> -->
			<!-- 异常通知:方法出现异常后执行 -->
			<!-- <aop:after-throwing method="afterThrowing" pointcut-ref="pointCut"/> -->
		
			<!-- 环绕通知 -->
			<aop:around method="around" pointcut-ref="pointCut"/>
		</aop:aspect>
	</aop:config>
</beans>
效果图:

情况一,在测试类中修改代码为:person.goHome("123");,效果如图所示:
Spring实战学习笔记整理(4)-AOP(面向切面编程)
情况二,在测试类中修改代码为:person.goHome("abc");,效果如图所示:
Spring实战学习笔记整理(4)-AOP(面向切面编程)

注解形式配置AOP

代码部分:

part1:

UserControllor.java

import org.springframework.stereotype.Controller;
/**
 * UserControllor,用于演示注解形式的切面编程
 * @author Katrina
 *
 */
@Controller
public class UserControllor {

	/**
	 * 添加用户操作
	 */
	public void addUser() {
		System.out.println("添加用户成功...");
	}
	
	/**
	 * 编辑用户操作
	 */
	public void editUser() {
		System.out.println("编辑用户成功...");
	}
	
}

LogAOP.java

import org.aspectj.lang.annotation.After;
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.springframework.stereotype.Component;
/**
 * 日志的切面
 * @author Katrina
 *
 */
@Component
@Aspect //标明LogAOP是切面类
public class LogAOP {

	/*
	 * 1.声明切点
	 * 2.声明通知
	 */
	@Pointcut(value = "execution(public * anno.UserControllor.*(..))")
	public void pointCut() { }
	
	/**
	 * 使用@Before声明前置通知
	 */
	@Before(value = "pointCut()")
	public void log() {
		System.out.println("在此处记录日志...");
	}
	
	/**
	 * 使用@After声明后置通知
	 */
	@After(value = "pointCut()")
	public void after() {
		System.out.println("后置通知执行了...");
	}
	
}

anno-config.java

<?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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

	<!-- 开启包扫描 -->
	<context:component-scan base-package="anno"></context:component-scan>

	<!-- 开启AOP -->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

UserControllorTest.java

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * 用于演示注解形式使用AOP
 * @author Katrina
 *
 */
public class UserControllorTest {

	@Test
	public void test() {
		//1.获取容器
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("anno-config.xml");
		//2.取出实例,做操作
		UserControllor userControllor = context.getBean(UserControllor.class);
		userControllor.addUser();
		//3.关闭容器
		context.close();
	}
	
}
效果图:

Spring实战学习笔记整理(4)-AOP(面向切面编程)

part2:

UserControllor.java

import org.springframework.stereotype.Controller;
/**
 * UserControllor,用于演示注解形式的切面编程
 * @author Katrina
 *
 */
@Controller
public class UserControllor {

	/**
	 * 添加用户操作
	 */
	public void addUser(String number) {
		System.out.println("添加用户成功...");

		Integer.parseInt(number); //解析,可制造错误(如:1/0)
	}
	
	/**
	 * 编辑用户操作
	 */
	public void editUser() {
		System.out.println("编辑用户成功...");
	}
	
}

LogAOP.java

import org.aspectj.lang.annotation.After;
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.springframework.stereotype.Component;
/**
 * 日志的切面
 * @author Katrina
 *
 */
@Component
@Aspect //标明LogAOP是切面类
public class LogAOP {

	/*
	 * 1.声明切点
	 * 2.声明通知
	 */
	@Pointcut(value = "execution(public * anno.UserControllor.*(..))")
	public void pointCut() { }
	
	/**
	 * 使用@Before声明前置通知
	 */
	@Before(value = "pointCut()")
	public void log() {
		System.out.println("在此处记录日志...");
	}
	
	/**
	 * 使用@After声明后置通知
	 */
	@After(value = "pointCut()")
	public void after() {
		System.out.println("后置通知执行了...");
	}
	
	/**
	 * 使用@AfterReturning声明返回通知
	 */
	@AfterReturning(value = "pointCut()")
	public void afterReturning() {
		System.out.println("方法成功执行了...");
	}

}
效果图:

情况一,在测试类中修改代码为:person.goHome("111");,效果如图所示:
Spring实战学习笔记整理(4)-AOP(面向切面编程)
情况二,在测试类中修改代码为:person.goHome("abc");,效果如图所示:
Spring实战学习笔记整理(4)-AOP(面向切面编程)

part3:

LogAOP.java

import org.aspectj.lang.annotation.After;
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.springframework.stereotype.Component;
/**
 * 日志的切面
 * @author Katrina
 *
 */
@Component
@Aspect //标明LogAOP是切面类
public class LogAOP {

	/*
	 * 1.声明切点
	 * 2.声明通知
	 */
	@Pointcut(value = "execution(public * anno.UserControllor.*(..))")
	public void pointCut() { }
	
	/**
	 * 使用@Before声明前置通知
	 */
	@Before(value = "pointCut()")
	public void log() {
		System.out.println("在此处记录日志...");
	}
	
	/**
	 * 使用@After声明后置通知
	 */
	@After(value = "pointCut()")
	public void after() {
		System.out.println("后置通知执行了...");
	}
	
	/**
	 * 使用@AfterReturning声明返回通知
	 */
	@AfterReturning(value = "pointCut()")
	public void afterReturning() {
		System.out.println("方法成功执行了...");
	}
	
	/**
	 * 使用@AfterThrowing表明异常通知
	 */
	@AfterThrowing(value = "pointCut()")
	public void afterThrowing() {
		System.out.println("发生异常了...");
	}
	
}
效果图:

情况一,在测试类中修改代码为:person.goHome("abc");,效果如图所示:
Spring实战学习笔记整理(4)-AOP(面向切面编程)
情况二,在测试类中修改代码为:person.goHome("111");,效果如图所示:
Spring实战学习笔记整理(4)-AOP(面向切面编程)

part4:

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.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
 * 日志的切面
 * @author Katrina
 *
 */
@Component
@Aspect //标明LogAOP是切面类
public class LogAOP {

	/*
	 * 1.声明切点
	 * 2.声明通知
	 */
	@Pointcut(value = "execution(public * anno.UserControllor.*(..))")
	public void pointCut() { }
	
	/**
	 * 使用@Before声明前置通知
	 */
//	@Before(value = "pointCut()")
	public void log() {
		System.out.println("在此处记录日志...");
	}
	
	/**
	 * 使用@After声明后置通知
	 */
//	@After(value = "pointCut()")
	public void after() {
		System.out.println("后置通知执行了...");
	}
	
	/**
	 * 使用@AfterReturning声明返回通知
	 */
//	@AfterReturning(value = "pointCut()")
	public void afterReturning() {
		System.out.println("方法成功执行了...");
	}
	
	/**
	 * 使用@AfterThrowing表明异常通知
	 */
//	@AfterThrowing(value = "pointCut()")
	public void afterThrowing() {
		System.out.println("发生异常了...");
	}
	
	/**
	 * 使用@Around注解声明环绕通知
	 * @param joinPoint
	 */
	@Around(value = "pointCut()")
	public void around(ProceedingJoinPoint joinPoint) {
		System.out.println("执行方法之前");
		
		try {
			joinPoint.proceed(); //执行业务方法
		} catch (Throwable e) {
			e.printStackTrace();
			System.out.println("出现异常了...");
		}
		
		System.out.println("执行方法之后");
	}
	
}
效果图:

情况一,在测试类中修改代码为:person.goHome("111");,效果如图所示:
Spring实战学习笔记整理(4)-AOP(面向切面编程)
情况二,在测试类中修改代码为:person.goHome("abc");,效果如图所示:
Spring实战学习笔记整理(4)-AOP(面向切面编程)

相关标签: Spring实战