AOP概念
AOP基本概念
- 连接点(JoinPoint):在AOP中表示“在哪里干”
- 切入点(Pointcut):在AOP中表示“在哪里干的集合”,可以认为是连接点的集合
- 通知(Advice):在AOP中表示为“干什么”,在Spring中主要包括:前置通知(before advice)、后置通知(after advice)以及环绕通知(around advice)
- 切面(Aspect):在AOP中表示“在哪里干和干什么的集合”
- 目标对象(Target Object):在AOP中表示“对谁干”
- **AOP代理(AOP Proxy):**AOP框架使用代理模式创建的对象,从而实现在连接点处插入通知(即应用切面),就是通过代理来对目标对象应用切面。在Spring中,AOP代理可以用JDK动态代理或CGLIB代理实现,而通过拦截器模型应用切面。
- 织入(Weaving):织入是一个过程,就是
将切面应用到目标对象从而创建出AOP代理对象的过程,织入可以在编译期、类装载期和运行期进行
Spring中通过Schema方式配置AOP
beans.xml基本配置
<bean id="helloWorldService" class="com.javacl.spring_learn.aop.HelloWordService"></bean> <bean id="aspect" class="com.javacl.spring_learn.aop.HelloAspect"></bean> <aop:config> <aop:pointcut expression="execution(* com.javacl.spring_learn..*.*(..))" id="poincut"/> <aop:aspect ref="aspect"> <aop:before method="beforeAdvice" pointcut-ref="poincut"/> <aop:after method="afterFinallyAdvice" pointcut-ref="poincut"/> </aop:aspect> </aop:config>
- 切面类基本配置
public class HelloAspect {
//前置通知
public void beforeAdvice() {
System.out.println("=======before advice");
}
//后置最终通知
public void afterFinallyAdvice() {
System.out.println("=======after finally advice");
}
}
- 接口类类基本配置
public interface IHelloWorldService {
public void sayHello();
}
- 目标对象类基本配置
public class HelloWordService implements IHelloWorldService {
public void sayHello() {
System.out.println("=======Hello World");
}
}
- 测试类
public class AopTest {
@Test
public void testHelloWorld() {
BeanFactory bf = new ClassPathXmlApplicationContext("beans.xml");
IHelloWorldService helloWorldService = bf.getBean("helloWorldService", IHelloWorldService.class);
helloWorldService.sayHello();
}
}
Spring中通过注解方式配置AOP
- 启动对@AspectJ注解的支持
<!-- 启用对Aspectj的支持 -->
<aop:aspectj-autoproxy />
- 定义切面类
/**
* 声明切面
*
* @author caoliang
*
*/
@Aspect
@Component
public class MyInterceptor {
/**
* 声明切入点Pointcut
*/
@Pointcut("execution (* com.javacl.spring_learn.aspectj..*.add*(..))")
public void pointCut() {
}
/**
* 前置通知
* @param param
*/
@Before("pointCut() && args(param)")
public void beforeAdvice(String param) {
System.out.println("这是一个前置通知" + param);
}
/**
* 后置通知
* @param result
*/
@AfterReturning(pointcut = "pointCut()", returning = "result")
public void returnAfterAdvice(String result) {
System.out.println("这是一个后置通知 result:" + result);
}
/**
* 最终通知
*/
@After("pointCut()")
public void afer() {
System.out.println("最终通知");
}
/**
* 异常通知
* @param joinPoint
* @param exception
*/
@AfterThrowing(pointcut = "pointCut()", throwing = "exception")
public void throwingException(JoinPoint joinPoint, Exception exception) {
// 获取被调用的类名
String targetClassName = joinPoint.getTarget().getClass().getName();
// 获取被调用的方法名
String targetMethodName = joinPoint.getSignature().getName();
String logInfo = "异常通知:执行" + targetClassName + "类的" + targetMethodName + "方法时发生异常";
System.out.println(logInfo);
}
/**
* 环绕通知
* @param proceedingJoinPoint
* @return
* @throws Throwable
*/
@Around(value="pointCut()")
public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
String targetMethodName = proceedingJoinPoint.getSignature().getName();
System.out.println("环绕通知开始");
Object object = proceedingJoinPoint.proceed();
String logInfo = "环绕通知结束:" + targetMethodName;
System.out.println(logInfo);
return object;
}
}
- 接口及接口实现类
public interface IUserService {
public String add(String name);
}
@Service(value="userService")
public class UserService implements IUserService {
public String add(String name) {
System.out.println("add " + name + " success");
//throw new RuntimeException();
return "add user success";
}
}
- 测试方法
@Test
public void testUserAdd() {
BeanFactory bf = new ClassPathXmlApplicationContext("beans.xml");
IUserService userService = bf.getBean("userService", IUserService.class);
userService.add("caoliang");
}
- 测试结果
环绕通知开始
这是一个前置通知caoliang
add caoliang success
环绕通知结束:add
最终通知
这是一个后置通知 result:add user success