✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
AOP 的全称是 Aspect Oriented Programming,即面向切面编程,它将业务逻辑的各个部
分进行隔离,使开发人员在编写业务逻辑时可以专心于核心业务,从而提高了开发效率。
AOP 采取横向抽取机制,取代了传统纵向继承体系的重复性代码,其应用主要体现在
事务处理、日志管理、权限控制、异常处理等方面。
目前最流行的 AOP 技术有两个,分别为 Spring 框架的 AOP 和 AspectJ 框架。
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
把一个个的横切关注点放到某个模块中去,称之为切面。每个切面影响业务的一种功能,
切面的目的就是为了功能增强,将需要增强的方法做成切面,实现对业务的增强,就是面向 切面编程。
面向切面编程的目的:将与业务本身无关,却被业务模块所共同调用的功能代码封装成 切面,以减少系统的重复代码,降低耦合,提高可扩展性。
面向切面编程的优势:把多个方法前/后的共同代码抽离出来,使用动态代理机制来控 制,先执行抽离出来的代码,再执行每一个真实方法。
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
为了更好地理解 AOP,就需要对 AOP 的相关术语有一些了解,这些专业术语主要包含
Joinpoint、Pointcut、Advice、Target、Weaving、Proxy 和 Aspect,它们的含义如下表所示
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
在使用Spring框架的AOP模块开发AOP时,需要添加核心容器的jar包以及aop的jar包
下载链接>>>>
注意:ThrowsAdvice接口是一个标识接口没有任何抽象对象.如果通知类型定义为异常通知,那么除了要实现ThrowsAdvice以外,还需要在切面中添加下面4个方法中的一个,并在该方法中实现具体的增强处理。
public void afterThrowing(Exception ex)
public void afterThrowing(RemoteException)
public void afterThrowing(Method method, Object[] args, Object target, Exception ex)
public void afterThrowing(Method method, Object[] args, Object target, ServletExcep
定义切面类
package wr.oyc.aop.aspect;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice;
import java.lang.reflect.Method;
public class MyAspect implements MethodBeforeAdvice,
AfterReturningAdvice, MethodInterceptor, ThrowsAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("Before...."+method.getName());
}
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("After...."+method.getName());
}
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("Around....Before" + methodInvocation.getMethod().getName());
Object obj = methodInvocation.proceed();
System.out.println("Around....After" + methodInvocation.getMethod().getName());
return obj;
}
public void afterThrowing(Exception ex){
System.out.println(ex.getMessage());
}
}
配置切面
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="usersService"
class="wr.oyc.aop.aspect.service.imp.UserServiceImpl"/>
<bean id="myAspect" class="wr.oyc.aop.aspect.MyAspect"/>
<bean id="usersServiceProxy"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces"
value="wr.oyc.aop.aspect.service.UserService"/>
<property name="target" ref="usersService"/>
<property name="interceptorNames">
<list>
<value>myAspectvalue>
list>
property>
<property name="proxyTargetClass" value="true"/>
bean>
beans>
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="usersService"
class="wr.oyc.aop.service.imp.UserServiceImpl"/>
<bean id="myAspect" class="wr.oyc.aop.aspect.MyAspect"/>
<bean id="toUppercaseAspect" class="wr.oyc.aop.aspect.ToUppercaseAspect"/>
<bean id="usersServiceProxy"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces"
value="wr.oyc.aop.service.UserService"/>
<property name="target" ref="usersService"/>
<property name="interceptorNames">
<list>
<value>myAspectvalue>
<value>toUppercaseAspectvalue>
list>
property>
<property name="proxyTargetClass" value="true"/>
bean>
beans>
测试类
package wr.oyc.aop.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import wr.oyc.aop.service.UserService;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext=
new ClassPathXmlApplicationContext("ApplicationContext_aop.xml");
UserService userService = (UserService) applicationContext.getBean("usersServiceProxy");
userService.addUsers("abc");
}
}
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
AspectJ 是一个基于 Java 语言的 AOP 框架。在 Spring 2.0 以后,新增了对 AspectJ 框 架的支持。在
Spring 框架中建议使用 AspectJ 框架开发 AOP。
AspectJ 配置方式是指使用 AspectJ 框架的配置方式来配置切面。在使用 AspectJ 配置切
面时,切面不需要实现一些特定的接口。
创建切面
package wr.oyc.aop.aspectj;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyAspect {
public void myBefore(JoinPoint joinPoint) {
//joinPoint.getTarget(); 获取目标对象
//joinPoint.getSignature().getName(); 获取目标方法名
//joinPoint.getArgs(); 获取目标方法参数列表
//joinPoint.getThis(); 获取代理对象
System.out.println("Before" + joinPoint.getSignature().getName());
}
public void myAfterReturning(JoinPoint joinPoint) {
System.out.println("After " + joinPoint.getSignature().getName());
}
public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("Around Before " + proceedingJoinPoint.getSignature().getName());
Object obj = proceedingJoinPoint.proceed();
System.out.println("Around After " + proceedingJoinPoint.getSignature().getName());
return obj;
}
public void myAfterThrowing(Exception e) {
System.out.println("Exception " + e);
}
public void myAfter() {
System.out.println("最终通知");
}
}
在 AspectJ 配置方式中,可以添加多个aop:aspect标签实现多切面配置。在aop:aspect
标签中包含 order 属性用于配置执行切面的执行顺序
Schema_based(基础模式)配置方式是指使用 Spring AOP 模块来定义切面并在 AspectJ 框架中对该切面进行配置。要求切面在定义通知类型时,需要实现特定接口。
在 Schema_based 配置方式中,可以添加多个aop:advisor标签实现多切面配置。在
aop:advisor标签中包含 order 属性用于配置执行切面的执行顺序
AspectJ 框架允许使用注解定义切面、切入点和增强处理,而 Spring 框架则可以识别并
根据这些注解生成 AOP 代理。
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨