持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天,点击查看活动详情 Aop
(1).简介
(2).Aop的作用及其优势
作用:在程序运行期间,在不修改源码的情况下对方法进行功能增强(动态代理)
优势:减少代码重复,提高开发效率,并且便于维护
(3).Aop的底层实现
Aop的动态代理技术
(4).基于jdk的动态代理
public class ProxyTest {
public static void main(String[] args) {
// 目标对象
final Target target = new Target();
// 增强对象
final Advice advice = new Advice();
// 返回值就是动态生成的代理对象
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(
// 目标对象类加载器
target.getClass().getClassLoader(),
// 目标对象类实现的接口的字节码对象数组
target.getClass().getInterfaces(),
// InvocationHandler接口: 内部实现功能增强
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置增强
advice.before();
Object res = method.invoke(target, args);
// 后置增强
advice.afterReturning();
return res;
}
});
proxy.save();
}
}
(5).Aop相关概念
1.Target(目标对象):代理的目标对象
2.Proxy(代理对象):一个类被Aop增强后,就会产生一个代理类
3.JoinPoint(连接点):可以被增强的方法
4.PointCut(切入点):已经被增强的方法
5.Advice(通知/增强):拦截到JoinPoint要做的事情
6.Aspect(切面):是切入点(已经被增强的方法)和通知的结合
7.Weaving(织入):将切点和通知结合的过程
(6).Aop入门
1.导入Aop相关坐标
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.11</version>
</dependency>
2.创建目标接口和目标类(内部有切点)
3.创建切面类(内部有增强方法)
public class MyAspect {
public void before(){
System.out.println("前置增强......");
}
}
4.将目标类和切面类的对象创建权交给Spring
<!-- 配置目标对象-->
<bean id="target" class="com.aop.Target"/>
<!-- 配置切面对象-->
<bean id="myAspect" class="com.aop.MyAspect"/>
5.在配置文件中配置织入关系
<!-- 配置织入(哪些方法需要被增强)-->
<aop:config>
<!-- 声明切面-->
<aop:aspect ref="myAspect">
<aop:before method="before" pointcut="execution(public void com.aop.Target.save())"/>
</aop:aspect>
</aop:config>
6.测试
(7).切点表达式
(8).通知的种类
环绕通知:
// ProceedingJoinPoint: 正在执行的连接点 : 切点
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕前增强");
Object proceed = proceedingJoinPoint.proceed();
System.out.println("环绕后增强");
return proceed;
}
如果同时配置了环绕增强和后置增强,会先执行环绕后增强然后再执行后置增强
如果同时配置了环绕增强和前置增强,会先执行环绕前增强然后再执行前置增强
(9).抽取切点表达式
<!-- 抽取切点表达式-->
<aop:pointcut id="myPointcut" expression="execution(* com.aop.*.*(..))"/>
<aop:around method="around" pointcut-ref="myPointcut"/>
(10).注解实现Aop
@Component("myAspect")
@Aspect // 表明这是一个切面类
public class MyAspect {
@Before("execution(* com.anno.*.*(..))")
public void before(){
System.out.println("前置增强......");
}
public void afterReturning(){
System.out.println("后置增强");
}
// ProceedingJoinPoint: 正在执行的连接点 : 切点
@Around("execution(* com.anno.*.*(..))")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕前增强");
Object proceed = proceedingJoinPoint.proceed();
System.out.println("环绕后增强");
return proceed;
}
}
<!-- 开启组件扫描-->
<context:component-scan base-package="com.anno"/>
<!-- Aop自动代理-->
<aop:aspectj-autoproxy/>