纯POJO方式实现AOP:
基于POJO的Advice通知
与基于代理实现AOP不同,基于POJO实现AOP时,通知类不需要继承其他接口,只需自定义前置通知和后置通知的方法并传入JoinPoint(连接点)参数,让通知可以与目标方法连接起来
import org.aspectj.lang.JoinPoint;
/*
* 基于AOP实现日志输出(POJO实现)
*/
public class LogAdvice{
// "自定义"前置通知方法
public void methodBefore(JoinPoint joinPoint){
System.out.println("[日志输出]:--------前置通知----------------");
}
// "自定义"后置通知方法
public void methodAfter(JoinPoint joinpoint){
System.out.println("[日志输出]:--------后置通知----------------");
}
}
同样的,对于环绕通知来说也需要传入一个ProceedingJoinPoint(连接点)参数做到环绕通知与目标方法的连接
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("[环绕通知]$$$$$$$$$$$$$$$$$$$$$$$$");
Object returnVal = joinPoint.proceed();
System.out.println("[环绕通知]*************************");
return returnVal;
}
基于POJO的AOP依旧在xml中配置,与基于代理的AOP不同。基于POJO的AOP省去了自动代理创建工厂的注入,胆识目标对象依旧会被创建出一个代理对象只不过创建代理对象的这部分交给Spring容器来帮我们实现,不需要我们自己创建代理对象
切点表达式:
execution(* com.lzq.dao.*.Insert(…))
execution表示在目标方法执行时触发
第一个表示返回任意类型
com.lzq.dao.*表示方法所属的类
.*Insert(…)表示所匹配的方法
用于配置通知的元素
<aop:config>
<!-- 配置切面 -->
<aop:aspect ref="logAdviceBean">
<!-- 切点,通过表达式查找目标方法 -->
<aop:pointcut expression="execution(* com.lzq.dao.*.*Insert(..))" id="daoInsertMethod"/>
<!-- 前置通知,在pointcut匹配的目标方法执行前自动执行前置通知 -->
<aop:before method="methodBefore" pointcut-ref="daoInsertMethod"/>
<aop:after method="methodAfter" pointcut-ref="daoInsertMethod"/>
</aop:aspect>
<!-- 配置切面 -->
<aop:aspect ref="admirAdviceBean">
<aop:pointcut expression="execution(* com.lzq.dao.*.*Insert(..))" id="daoInsertMethod"/>
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="daoInsertMethod"/>
</aop:aspect>
</aop:config>
基于@AspectJ注解的AOP:
与基于代理和基于POJO不同,基于AspectJ注解的AOP摄取了xml配置文件,转为更为简便的注解配置,在使用Aspectj时需要注入第三方的依赖,但是Spring帮我们集成了进来
<!--AspectJ相关依赖-->
<!--依赖1: aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.5</version>
</dependency>
<!-- 依赖2: aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
在配置注解时需要用到的注解有这些:
@EnableAspectJAutoProxy
注册AutoProxyCreator自动代理创建工厂
这个注解是用在主配置类上在spring容器开始扫描的时候就已经将自动代理创建工厂注册了进来
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan
@EnableAspectJAutoProxy//注册AutoProxyCreator自动代理创建工厂
public class AppConfig {
}
@Aspect
声明切面
这个注解用在通知类上
@Pointcut
声明切点
这个注解用在方法上,当我们的容器中同时又前后置通知,环绕通知的时候,我们创建了一个公共的类用于封装pointcut所匹配的方法
//公共的类用于封装pointcut所匹配的方法
public class MyPointcut {
@Pointcut("execution(* com.lzq.dao.*.*Insert(..))")
public void daoInsertMethod() {
}
@Pointcut("execution(* com.lzq.dao.*.*Update(..))")
public void daoUpdateMethod() {
}
}
然后就是关于通知的注解
@Before
表示前置通知,用在方法上
@After
表示后置通知,用在方法上
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LogAdvice02 {
//根据包名+类名+方法名的方式来为通知匹配需要织入通知的目标方法
//前置通知
@Before("com.lzq.aspectj.MyPointcut.daoInsertMethod()")
public void methodBefore(JoinPoint joinPoint){
System.out.println("[日志输出]:--------前置通知----------------");
}
//根据包名+类名+方法名的方式来为通知匹配需要织入通知的目标方法
//后置通知
@After("com.lzq.aspectj.MyPointcut.daoInsertMethod() || com.lzq.aspectj.MyPointcut.daoUpdateMethod()" )
public void methodAfter(JoinPoint joinpoint){
System.out.println("[日志输出]:--------后置通知----------------");
}
}
@Around
环绕通知,用在方法上
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class AdmirAdvice {
//环绕通知
@Around("com.lzq.aspectj.MyPointcut.daoInsertMethod()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("[环绕通知]$$$$$$$$$$$$$$$$$$$$$$$$");
Object returnVal = joinPoint.proceed();
System.out.println("[环绕通知]*************************");
return returnVal;
}
}