spring AOP——用注解的方式实现
目录
说明
本例子不是web项目。
配置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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 开启自动扫描text3_AOP_text4包下的所以类的注释 -->
<context:component-scan base-package="text3_AOP_text4" />
<!-- 开启aspectj注释 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
说明:
用注解的方式,可以大大的减少配置操作
切面类MyAspect.java
切面类:MyAspect.java,代码片
.
package text3_AOP_text4;
import org.aspectj.lang.JoinPoint;
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;
//注册一个bean,是一个切面
@Component
@Aspect
public class MyAspect {
// 连接点,方法
@Pointcut("execution(* text3_AOP_text3.StudentImpl.*(..))")
public void pointcut1() {
}
// 连接点,类
@Pointcut(argNames = "pointcut2", value = "within(text3_AOP_text3.StudentImpl.*)")
public void pointcut2() {
}
// 前置通知方法
@Before("pointcut()")
public void before(JoinPoint joinPoint) {
System.out.println("前置通知---方法名: " + joinPoint.getSignature().getName());
}
// 带参数的前置通知方法,且参数名是(arg1,arg2,arg3,...)
@Before("pointcut() && args(arg1,arg2,arg3)")
public void beforeWithParam(JoinPoint joinPoint,String arg1, String arg2, String arg3) {
System.out.println(arg1);
}
// 带参数的前置通知方法,且可以获得附加参数,@Method类型是一个注解,自定义参数名Method
@Before("pointcut() && @annotation(Method)")
public void beforeWithAnnotaion(Method Method) {
System.out.println("BeforeWithAnnotation." + Method.value());
}
// 返回后通知方法,返回值名re,
@AfterReturning(pointcut = "pointcut2", returning = "re")
public void afterReturning(JoinPoint joinPoint, Object re) {
System.out.println("后置通知---方法名: " + joinPoint.getSignature().getName() + ", 返回参数re: " + re);
}
// 异常通知方法,异常变量为e
@AfterThrowing(pointcut = "pointcut()", throwing = "e")
public void afterThrowing(JoinPoint joinPoint, Throwable e) {
System.out.println("异常通知: " + "出现异常的方法名: " + joinPoint.getSignature().getName() + ", 异常信息e: " + e.getMessage());
System.exit(0);
}
// 后通知方法
@After("pointcut()")
public void after(JoinPoint joinPoint) {
System.out.println("后通知---方法名: " + joinPoint.getSignature().getName());
}
// 环绕通知方法
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint) {
Object re = null;
try {
System.out.println("环绕通知前");
re = joinPoint.proceed();
System.out.println("环绕通知后");
} catch (Throwable e) {
e.printStackTrace();
}
return re;
}
// 有参数的环绕通知方法,执行的上下文ProceedingJoinPoint
@Around("pointcut() && args(name)")
public Object aroundInit(ProceedingJoinPoint joinPoint, String name) {
System.out.println("姓名:" + name);
Object re = null;
try {
System.out.println("环绕通知前");
re = joinPoint.proceed();
System.out.println("环绕通知后");
} catch (Throwable e) {
e.printStackTrace();
}
return re;
}
//在使用People对象时,可以自主的将People对象强制转为FBIImpl对象
@DeclareParents(value = "text3_AOP_text3.People", defaultImpl = text3_AOP_text4.FBIImpl.class)
public FBI fbi;
}
说明:
--------------------------------------------------------------------------------------------------------------------------------------------
* 了解一下spring aop的两个接口的主要方法:
* 1)JoinPoint
* java.lang.Object[] getArgs():获取连接点方法的参数集合
* Signature getSignature() :获取连接点的方法对象;
* java.lang.Object getTarget() :获取连接点所在类的目标对象;
* java.lang.Object getThis():获取切面对象本身;
* 2)ProceedingJoinPoint
* ProceedingJoinPoint继承JoinPoint子接口,新增了两个用于执行连接点方法的方法:
* java.lang.Object proceed() throws java.lang.Throwable:通过反射执行目标对象的连接点处的方法;
* java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象连接点处的方法,不过使用新的入参替换原来的入参。
*
spring不能自动识别Aspect注解,需要带上@Component注解来标注
自定义注解@Method
@Method注解,代码片
.
package text3_AOP_text4;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//方法上,运行时
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Method {
String value();
}
说明:
注解用在方法上,运行时有效
总结
1. 使用注解的方式来实现AOP相对于API方式和配置方式更加方便,可以大大的简化开发过程。
**引用包是最大的困难(一步一步来)**