SpringAOP(切面编程)解耦合,在运行时耦合到一起运行

AOP
作用:在程序运行期间,在不修改源码情况下对方法功能进行功能增强
优势:减少重复代码,解耦合,便于维护

常用动态代理两种方式:
JDK代理:基于接口的动态代理技术
cglib代理:基于父类的动态代理技术

JDK代理方式代码书写

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyTest {
    public static void main(String[] args) {
        Target target = new Target();
        Advice advice = new Advice();

        // 返回值就是动态生成的代理对象
        TargetInterface proxyInstance = (TargetInterface) Proxy.newProxyInstance(
                target.getClass().getClassLoader(), // 目标对象类加载器
                target.getClass().getInterfaces(), //目标对象相同的接口字节码对象组
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        advice.preAdvice(); // 前置增强
                        method.invoke(target,args); // 执行目标方法
                        advice.postAdvice();  // 后置增强
                        return null;
                    }
                }
        );

        // 调用代理对象的方法
        proxyInstance.save();
    }

}

cglib代理代码书写



import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class ProxyTest {
    public static void main(String[] args) {
        // 目标对象
        Target target = new Target();
        // 增强对象
        Advice advice = new Advice();

        // 返回值就是动态生成的代理对象, 基于cglib
        // 1、创建增强器
        Enhancer enhancer = new Enhancer();
        // 2、设置父类
        enhancer.setSuperclass(Target.class);
        // 3、设置回调
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                advice.preAdvice(); // 前置增强
                Object invoke = method.invoke(target, objects);// 传入对象和相应参数
                advice.postAdvice(); // 后置增强
                return invoke;
            }
        });

        // 4、创建代理对象
        Target targetProxy = (Target) enhancer.create();
        targetProxy.save();
    }

}

SpringAOP实现
Spring框架监控切入点方法的执行,一旦监控到切入方法的执行使,用代理机制动态创建目标对象的代理对象。根据通知类别在代理对象的对应位置,将通知对应的功能织入,完成完整代码逻辑的运行。

需要明确事项:
1、谁是切点
2、谁是通知(增强)
3、将切点和通知进行织入配置

切点表达式:

  1. 访问修饰符可省略
  2. 返回值类型、包名、方法名、可以使用*替代任意
  3. 报名中间一个.表示当前包下的类,两个…代表当前包下及其子包下的类
  4. 参数列表可以使用…表示任意个数和任意参数类型
  5. 可通过配置进行切点表达式抽取
 execution(public void com.AOP.Target.save()) // 表示sava方法
 execution(void com.AOP.Targer.*(..)) // Target类下的所有方法
 execution(* com.AOP.*.*(..)) // AOP包和其下面的包下的所有方法

几种增强方式:

前置增强:before
后置增强:after-returning
环绕增强:around(需要传入参数 ProceedingJoinPoint proceedingJoinPoint)在方法中执行Object proceed = proceedingJoinPoint.proceed(); 返回proceed
抛出异常增强:after-throwing
最终增强:after

配置文件:


    <aop:config>
        <aop:aspect ref="myAspect">
            <!-- 切点表达式抽取-->
            <aop:pointcut id="myPointcut" expression="execution(* com.AOP..*(..))"/>
            <!-- 前置增强-->
            <aop:before method="before" pointcut-ref="myPointcut"/>
            <!-- 后置增强-->
            <aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/>
            <!-- 环绕增强-->
            <aop:around method="around" pointcut-ref="myPointcut"/>
            <!-- 抛出异常增强-->
            <aop:after-throwing method="afterThrowing" pointcut-ref="myPointcut"/>
            <!-- 最终增强,无论是否发生异常都会最终执行-->
            <aop:after method="after" pointcut-ref="myPointcut"/>
        </aop:aspect>
    </aop:config>

增强方法:


import org.aspectj.lang.ProceedingJoinPoint;

public class MyAspect {
    public void before() {
        System.out.println("前置增强.......");
    }

    public void afterReturning() {
        System.out.println("后置增强.......");
    }

    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("前置环绕增强.......");
        Object proceed = proceedingJoinPoint.proceed();
        System.out.println("后置环绕增强.......");
        return proceed;
    }

    public void afterThrowing() {
        System.out.println("异常抛出增强.......");
    }

    public void after() {
        System.out.println("最终增强.......");
    }
}

注解方式:

开发步骤:

  1. 使用@Aspect标注切面类
  2. 使用@通知注解标注通知方法
  3. 在配置文件中配置AOP自动代理aop:aspectj-autoproxy
  4. 可使用@Pointcut抽取切点表达式
    切面类:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect
@Component("myAspect")
public class MyAspect {
    @Pointcut("execution(* com.AnnoAOP..*(..))")
    public void myPointcut(){}

    @Before("myPointcut()")
    public void before() {
        System.out.println("前置增强.......");
    }

    @AfterReturning("MyAspect.myPointcut()")
    public void afterReturning() {
        System.out.println("后置增强.......");
    }

    @Around("execution(* com.AnnoAOP..*(..))")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("前置环绕增强.......");
        Object proceed = proceedingJoinPoint.proceed();
        System.out.println("后置环绕增强.......");
        return proceed;
    }

    @AfterThrowing("execution(* com.AnnoAOP..*(..))")
    public void afterThrowing() {
        System.out.println("异常抛出增强.......");
    }

    @After("execution(* com.AnnoAOP..*(..))")
    public void after() {
        System.out.println("最终增强.......");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值