AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
使用配置
包含如下依赖:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.4</version>
</dependency>
build/plugins下增加:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.8</version>
<configuration>
<complianceLevel>${java-version}</complianceLevel>
<source>${java-version}</source>
<target>${java-version}</target>
<encoding>UTF-8</encoding>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
xml文件增加如下配置:
<aop:aspectj-autoproxy />
使用案例
要切的接口:
public interface Handler {
List<ProcessResult> process(InputArg arg1, InputArg[] arg2);
}
接口的其中一个实现:
@Service
public class DefaultHandler implements Handler {
@Override
public List<ProcessResult> process(InputArg arg1, InputArg[] arg2) {
return null;
}
}
切面的实现:
@Aspect
public class HandlerAspect {
@Pointcut("execution(public * com.chuxing.example.Handler.process(..))")
public void method() {}
@Around("method()")
public Object doAround(ProceedingJoinPoint jp) throws Throwable {
Class<?> clazz = jp.getTarget().getClass();
increaseTryTimes(clazz);
Object result = jp.proceed();
try {
if (result != null && result instanceof List) {
List<ProcessResult> ProcessResults = (List<ProcessResult>) result;
if (CollectionUtils.isEmpty(ProcessResults)) {
increaseFailTimes(clazz);
}
return ProcessResults;
} else {
increaseFailTimes(clazz);
}
} catch (Exception ex) {
increaseFailTimes(clazz);
throw new Exception(ex.getMessage());
}
return result;
}
private void increaseFailTimes(Class<?> clazz) {
//do something
}
private void increaseTryTimes(Class<?> clazz) {
//do something
}
}
两种配置方式
注解配置AOP
- 使用注解@Aspect来定义一个切面,在切面中定义切入点(@Pointcut),通知类型(@Before, @AfterReturning,@After,@AfterThrowing,@Around).
- 开发需要被拦截的类。
- 将切面配置到xml中,当然,我们也可以使用自动扫描Bean的方式。这样的话,那就交由Spring AoP容器管理。
另外需要引用 aspectJ 的 jar 包: aspectjweaver.jar aspectjrt.jar
xml配置AOP
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
<!-- 要添加最后2行 -->
<context:annotation-config />
<context:component-scan base-package="com.chuxing.example"/>
<bean id="handlerAspect" class="com.chuxing.example.HandlerAspect"></bean>
<aop:config>
<aop:pointcut expression="execution(public * com.chuxing.example.Handler.process(..))"
id="handlerPointcut"/>
<aop:aspect ref="handlerAspect">
<aop:before method="doAround" pointcut-ref="handlerPointcut" />
</aop:aspect>
</aop:config>
</beans>