AOP
什么是AOP?
AOP是指面向切面编程,是通过动态代理的方式为程序添加统一功能,解决一些公共问题,如:日志、鉴权和异常处理等。
好处:降低代码耦合度,使开发人员聚焦业务,公共统一处理,修改方便。
AOP的术语
1、切面Aspect:多个类都关注的方法
2、连接点Join point:代表一个方法的调用
3、Advice通知:我们要在切面上做什么事情(动作-action)
4、Pointcut切入点:用来描述我们要在哪些地方执行
5、Target object目标对象:被一个或多个切面通知的对象
AOP有哪些常用的注解?
@Aspect:在类上使用@Aspect可使之成为切面类
@Before(“execution(* com.qcc.beans.aop..(…))”):前置通知
@After(“execution(* com.qcc.beans.aop..(…))”):后置通知
@Around(“execution(* aop.service.impl.BusinessServiceImpl.(…))"):环绕通知,可以在方法的调用前后完成自定义行为,甚至可以选择不调用方法和修改返回对象,这是和前置后置通知的区别。
@AfterThrowing(value="execution( com.qcc.beans.aop..(…))”,throwing=“e”):异常通知
@AfterReturning(value=“execution(* com.qcc.beans.aop..(…))”,returning=“result”):返回通知
如何实现AOP?
举例:设计性能拦截器,用于打印服务层所有方法的执行时间。
1、业务服务接口
public interface IBusinessService {
//业务执行方法A
void executeBusinessA();
//业务执行方法B
void executeBusinessB();
}
2、业务实现类
@Service("businessService")
public class BusinessServiceImpl implements IBusinessService {
public void executeBusinessA() {
logger.info("executing business in methodA");
}
public void executeBusinessB() {
logger.info("executing business in methodB");
}
}
3、性能分析器
@Component // 放入IOC容器
@Aspect // 切面类
public class PerformanceAnalysisInterceptor {
// 切入点是所有方法
public static final String POINTCUT =
"execution (* aop.service.impl.BusinessServiceImpl.*(..))";
@Around(POINTCUT)
public Object analysisAround(ProceedingJoinPoint joinPoint) {
Object obj = null;
long startTime = System.currentTimeMillis();
try {
obj = joinPoint.proceed(joinPoint.getArgs());
} catch (Throwable e) {
logger.error(e.getMessage());
}
long endTime = System.currentTimeMillis();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String methodName = signature.getDeclaringTypeName() + "." + signature.getName();
long diffTime = endTime - startTime;
logger.info("-----" + methodName + "执行时间 :" + diffTime + " ms");
return obj;
}
}
4、xml配置
<context:component-scan base-package="aop"/>
<aop:aspectj-autoproxy/>
5、主函数调用
public class AopMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext f =
new ClassPathXmlApplicationContext("spring-aop.xml");
IBusinessService businessService = (IBusinessService) f.getBean("businessService");
businessService.executeBusinessA();
businessService.executeBusinessB();
}
}
6、打印
executing business in methodA
aop.service.IBusinessService.executeBusinessA执行时间 :203 ms
executing business in methodB
aop.service.IBusinessService.executeBusinessB执行时间 :1003 ms
AOP的实现原理?
以上面的AOP实现为例分析AOP的实现原理:
1、@Component
@Component会让Spring将切面类加入Spring的Bean容器;
2、@Aspect
@Aspect告诉Spring该Bean是一个拦截器,Spring就会去其中寻找所有的拦截方法和拦截规则。
3、创建代理
Spring有2种方式创建代理:JDK动态代理和CGLIB代理。
spring选择策略:
(1)如果目标类实现了接口,默认采用jdk动态代理来实现AOP
(2)如果目标类实现了接口,可以通过配置文件强行使用CGLib来实现AOP代理
(3)如果目标类没有实现接口,只能使用CGlib来实现AOP代理。
【注】CGlib可以为那些没有实现接口的类增强行为,原理是为目标类生成一个子类,并覆盖其中的方法