SpringAOP

1.日志处理的问题



2.什么是AOP?

通过代理模式,可以在指定位置执行对应流程。这样就可以将一些横向的功能抽离出来形成一一个独立的模块, 然后在指定位置插入这些功能。这样的思想,被称为面向切面编程,即AOP.
Aspect Oriented Programing面向切面编程,相比较oop面向对象编程来说,Aop关注的不再是程序代码中某个类,某些方法,而aop考虑的更多的是一种面到面的切入,即层与层之间的一种切入,所以称之为切面。

3.AOP能做什么?

AOP主要应用于日志记录,性能统计,安全控制,事务处理等方面,实现公共功能性的重复使用。

4.AOP的特点

1.降低模块与模块之间的耦合度,提高业务代码的聚合度。(高内聚低耦合)
2.提高了代码的复用性。
3.提高系统的扩展性。(高版本兼容低版本)
4.可以在不影响原有的功能基础上添加新的功能

5.AOP的底层实现

动态代理(JDK + CGLIB)

6.AOP基本概念

6.1. Joinpoint (连接点)

被拦截到的每个点工spring中指被拦截到的每一个方法, spring aop-个连接点即代表-个方法的执行。

6.2. Pointcut (切入点)

对连接点进行拦截的定义(匹配规则定义规定拦截哪些方法,对哪些方法进行处理) , spring 有专门的表达式语言定义。

6.3. Advice (通知)

拦截到每一个连接点即(每一个方法) 后所要做的操作
1.前置通知(前置增强) - before() 执行方法前通知
2.返回通知(返回增强) - afterReturn 方法正常结束返回后的通知
3.异常抛出通知(异常抛出增强) - afetrThrow()
4.最终通知- after无论方法是否发生异常,均会执行该通知。
5.环绕通知- around包围一个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型。环绕通知可以在方法调用前后完成自定义的行为。
它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。

6.4. Aspect (切面)

切入点与通知的结合,决定了切面的定义,切入点定义了要拦截哪些类的哪些方法
通知则定义了拦截过方法后要做什么,切面则是横切关注点的抽象,与类相似,类是对物体特征的抽象,切面则是横切关注点抽象。

6.5. Target (目标对象)

被代理的目标对象

6.6. Weave (织入)

将切面应用到目标对象并生成代理对象的这个过程即为织入

6.7. Introduction (引入)

在不修改原有应用程序代码的情况下,在程序运行期为类动态添加方法或者字段的过程称为引入

7.AOP实现

7.1 注解实现

aspect包里的LogCut类

/**
 * 切面
 *  切入点:定义拦截哪些类的那些方法
 *  通知: 定义拦截之后方法做什么事情
 *
 */
@Component //将对象交给IOC容器进行实例化
@Aspect //声明当前类是一个切面
public class LogCut {
    /**
     * 切入点
     *      表达式:
     *      1.所有公共方法 public *(..)
     *      方法修饰范围(public,private,protected,*)
     *      2.任意set方法
     *          * set*(..)
     *      3.指定包下的任意类任意方法 * org.example.service.*.*(..)
     *      4.指定包及子包下的任意类的任意方法
     *          * org.example.service.。*.*(..)
     */
    @Pointcut("execution(* org.example.service.*.*(..))")
    public void cut(){

    }

    /**
     * 前置通知
     *      目标类的方法执行前 执行该通知
     */
    @Before(value = "cut()")
    public void before(){

    }

    /**
     * 返回通知
     *  目标类的方法在无异常执行后执行该通知
     */
    @AfterReturning(value = "cut()")
    public void afterReturn(){

    }

    /**
     * 最终通知
     *      无论有无异常都会执行
     */
    @After(value = "cut()")
    public void after(){

    }


    /**
     * 异常通知
     *      有异常通知
     */
    @AfterThrowing(value = "cut()",throwing = "e")
    public void afterThrow(Exception e){
        System.out.println("throw");
        System.out.println(e.getMessage());
    }

    /**
     * 环绕通知
     *      目标类执行前后都可执行
     *      需要通过显式调用方法
     *      比别的通知先执行
     * @param pjp
     * @return
     */
    @Around(value = "cut()")
    public Object around(ProceedingJoinPoint pjp){
        Object object=null;

        try{
            //显式调用对应方法
            object=pjp.proceed();
            System.out.println(pjp.getTarget());
            System.out.println("返回通知");
        }catch (Throwable throwable){
            //被环绕通知catch后不会执行异常通知
            throwable.printStackTrace();
            System.out.println("异常通知");

        }
        System.out.println("最终通知");

        return object;
    }
}

spring.xml中

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd ">

<!--        开启自动化扫描-->
        <context:component-scan base-package="org.example"/>

<!--        配置AOP代理-->
         <aop:aspectj-autoproxy/>
</beans>

Test类中进行实现

public static void main(String[] args) {
        //获取上下文环境
        ApplicationContext ac=new ClassPathXmlApplicationContext("spring.xml");
        //获取指定bean
        UserService userService=(UserService) ac.getBean("userService");
        userService.test();
    }

7.2 XML实现

Logcut1类中无注解

@Component //将对象交给IOC容器进行实例化
@Aspect //声明当前类是一个切面
public class LogCut1 {

    public void cut(){

    }

    /**
     * 前置通知
     *      目标类的方法执行前 执行该通知
     */

    public void before(){
        System.out.println("before");
    }

    /**
     * 返回通知
     *  目标类的方法在无异常执行后执行该通知
     */

    public void afterReturn(){

    }

    /**
     * 最终通知
     *      无论有无异常都会执行
     */

    public void after(){

    }


    /**
     * 异常通知
     *      有异常通知
     */

    public void afterThrow(Exception e){
        System.out.println("throw");
        System.out.println(e.getMessage());
    }

    /**
     * 环绕通知
     *      目标类执行前后都可执行
     *      需要通过显式调用方法
     * @param pjp
     * @return
     */

    public Object around(ProceedingJoinPoint pjp){
        Object object=null;

        try{
            //显式调用对应方法
            object=pjp.proceed();
            System.out.println(pjp.getTarget());
            System.out.println("返回通知");
        }catch (Throwable throwable){
            throwable.printStackTrace();
            System.out.println("异常通知");

        }
        System.out.println("最终通知");

        return object;
    }
}

spring1.xml中

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd ">

<!--        开启自动化扫描-->
        <context:component-scan base-package="org.example"/>

<!--        aop配置-->
        <aop:config>
<!--            aop切面-->
            <aop:aspect ref="logCut1">
<!--                aop切入点-->
                <aop:pointcut id="cut" expression="execution(* org.example.service..*.*(..))"/>
<!--                前置通知-->
                <aop:before method="before" pointcut-ref="cut"></aop:before>
<!--                返回通知-->
                <aop:after method="after" pointcut-ref="cut"></aop:after>
<!--                最终通知               -->
                <aop:after-returning method="afterReturn" pointcut-ref="cut"></aop:after-returning>
<!--                异常通知-->
                <aop:after-throwing method="afterThrow" pointcut-ref="cut" throwing="e"></aop:after-throwing>
<!--                环绕通知-->
                <aop:around method="around" pointcut-ref="cut"></aop:around>
            </aop:aspect>
        </aop:config>
</beans>
posted @   lwx_R  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
历史上的今天:
2021-08-30 微信公众号获取m3u8地址
点击右上角即可分享
微信分享提示