AspectJ是一个基于java语言的AOP框架,它提供了强大的AOP功能。
基于xml的声明式AspectJ是通过xml文件来定义切面、切入点、及通知,所有的切面、切入点和通知都必须在<aop:config>元素内。
1.配置切面
配置切面使用<aop:aspect>元素,配置<aop:aspect>元素时,通常指定id和ref两个属性:id:用于定义该切面的唯一标识名。 ref:用于引用普通的Spring Bean
2.配置切入点
在Spring的配置文件中,切入点是通过<aop:pointcut>元素来定义的。当<aop:pointcut>元素作为<aop:config>元素的子元素定义时,表示该切入点是全局切入点,它可被多个切面所共享;当<aop:pointcut>为<aop:aspect>元素的子元素时,表示该切入点只对当前切面有效。在定义<aop:pointcut>元素时,通常会指定id和expression两个属性。
id:用于指定切入点的唯一标识名称
expression:用于指定切入点关联的切入点表达式。
3.配置通知
在配置通知中,分别使用<aop:aspect>的子元素配置5种常用通知,这五个子元素不支持使用子元素,但在使用时可以指定一些属性。
pointcut:该属性指定一个切入点表达式,Spring将在匹配该表达式的连接点织入通知。
point-ref:该属性指定一个存在的切入点名称。通常pointcut和point-ref两个属性只使用其中一个。
method:概述性指定一个方法名,指定将切面Bean中的该方法转换为增强处理
throwing:该属性只对<after-throwing>元素有效,它用于指定一个形参名,异常通知可以通知该形参名访问目标所抛出的异常。
returning:该属性只对<after-returning>属性有效,它用于指定一个形参名,后置通知可以通过该形参名访问目标的返回值。
4.练习
(1)jar包,新增 spring-aspects-4.3.6.RELEASE.jar和aspectj-weaver.jar
(2)在src下,创建com.items.aspectj包,在com.items.aspectj包下创建接口,接口类,切面,和xml文件,以及测试类。
(3)UserDao接口
package com.items.aspectj;
public interface UserDao {
public void hello();
public void hello2();
}
(4)UserDao接口的实现类UserDaoIml
package com.items.aspectj;
public class UserDaoIml implements UserDao{
@Override
public void hello() {
System.out.println("运行中1。。。");
}
@Override
public void hello2() {
System.out.println("运行中2。。。");
}
public static void main(String [] args){
UserDao userDao = new UserDaoIml();
userDao.hello();
}
}
(5)切面MyAspect
package com.items.aspectj;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
/*
* 切面类,在此类中编写通知
*/
public class MyAspect {
//前置通知
public void myBefore(JoinPoint joinPoint) {
System.out.println("前置通知:模拟执行权限。。。。");
System.out.println("目标类是:" + joinPoint.getTarget());
System.out.println("被增强的目标类的方法是" + joinPoint.getSignature().getName());
}
//后置通知
public void myAfterReturn(JoinPoint joinPoint) {
System.out.println("后置通知:模拟日志记录....");
System.out.println("被增强的目标类的方法是" + joinPoint.getSignature().getName());
}
/*
* 环绕通知
* ProceedingJoinPoint是JoinPoint的子接口
* 必须是Object的返回值
* 必须接收一个参数类型为ProceedingJoinPoint
* 必须throws Throwable
*/
public Object myAroud(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕开始:模拟开启事务...");
//执行当前目标方法
Object obj = proceedingJoinPoint.proceed();
System.out.println("环绕结束:模拟关闭事务...");
return obj;
}
//异常通知
public void myAfterThrows(JoinPoint joinPoint, Throwable e){
System.out.println("异常通知:" + "出错了:" + e.getMessage());
}
//最终通知
public void myAfter(){
System.out.println("最终通知:模拟方法结束释放资源");
}
}
(6) aplicationContext.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 definitions here -->
<!--目标类 -->
<bean id="userDao" class="com.items.aspectj.UserDaoIml"></bean>
<!-- 切面 -->
<bean id="myAspect" class="com.items.aspectj.MyAspect"></bean>
<!-- aop编程 -->
<aop:config>
<!-- 配置切面 -->
<aop:aspect ref="myAspect">
<!-- 配置切入点,增强哪些方法 -->
<aop:pointcut expression="execution(* com.items.aspectj.*.*(..))" id="myPoinCut"/>
<!-- 关联通知advice和切入点pointCut -->
<!-- 前置通知 -->
<aop:before method="myBefore" pointcut-ref="myPoinCut"/>
<!-- 后置通知,在方法返回之后执行,就可以获得返回值 -->
<!--returning属性:用于设置后置通知的第二个参数的名称,类型为Object -->
<aop:after-returning method="myAfterReturn" pointcut-ref="myPoinCut" returning="returnVal"/>
<!-- 环绕通知 -->
<aop:around method="myAroud" pointcut-ref="myPoinCut"/>
<!-- 抛出通知:用于处理程序抛出异常
如果程序没有异常将不会执行 -->
<aop:after-throwing method="myAfterThrows" pointcut-ref="myPoinCut" throwing="e"/>
<!-- 最终通知:无论程序发生什么,都会执行 -->
<aop:after method="myAfter" pointcut-ref="myPoinCut"/>
</aop:aspect>
</aop:config>
</beans>
(6)测试类AspectTest
package com.items.aspectj;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AspectTest {
public static void main(String [] args) {
String xmlPath = "com/items/aspectj/aplicationContext.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
userDao.hello();
}
}
学习书籍:《javaEE企业级开发程序》