Spring AOP实现方式

什么是AOP

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方
式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个
热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑
的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高
了开发的效率。
编程中,对象与对象之间,方法与方法之间,模块与模块之间都是一个个切面。

实现方式一,主要实现Spring的api接口

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

    <!--开启注解的支持-->
    <context:annotation-config/>
    <!--方式一:使用原生Spring api接口-->
    <bean id="log" class="com.liu.log.Log"/>
    <bean id="AfterLog" class="com.liu.log.AfterLog"/>
    <bean id="UserService" class="com.liu.service.UserServiceImpl"/>

    <aop:config>
        <!--切入点expression(表达式) execution(切入位置)-->
        <aop:pointcut id="pointCut" expression="execution(* com.liu.service.UserServiceImpl.*(..))"/>
        <!--执行环绕增强        哪个类,              切入到哪里-->
        <aop:advisor advice-ref="log" pointcut-ref="pointCut"/>
        <aop:advisor advice-ref="AfterLog" pointcut-ref="pointCut"/>
    </aop:config>

</beans>

切入的内容

放切入点前

package com.liu.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Log  implements MethodBeforeAdvice {

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
//method:被调用的方法
//args:方法的参数
//target:方法调用的目标。可能为空
        System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");

    }
}

放在切入点后

package com.liu.log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
//returnValue 返回结果
//method:     被调用的方法
//args:      方法的参数
//target:     方法调用的目标。可能为空
        System.out.println("执行完了"+method.getName()+"返回结果为"+returnValue);
    }
}

一个接口一个实现

实现方式二 主要切面定义

增加放在切入点前后的方法

public class DiyPioncut {
    public void before(){System.out.println("============切入点前================");}
    public void after(){System.out.println("============切入点后================");}
}

配置applicationContext.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
       https://www.springframework.org/schema/aop/spring-aop.xsd
">
    <!--开启注解的支持-->
    <context:annotation-config/>
    <!--方式一:使用原生Spring api接口-->
    <bean id="log" class="com.liu.log.Log"/>
    <bean id="AfterLog" class="com.liu.log.AfterLog"/>
    <bean id="UserService" class="com.liu.service.UserServiceImpl"/>
    <bean id="diy" class="com.liu.DIY.DiyPioncut"/>


    <!--方式二-->
    <aop:config>
        <aop:aspect id="diyPointcut" ref="diy">
            <aop:pointcut id="point" expression="execution(* com.liu.service.UserServiceImpl.*(..))"/>
        <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
</beans>

execution表达式

execution(* com.loongshawn.method.ces..*.*(..))
标识符 含义
execution() 表达式的主体
第一个“*”符号 表示返回值的类型任意
com.loongshawn.method.ces AOP所切的服务的包名,即,需要进行横切的业务类
包名后面的“..” 表示当前包及子包
第二个“*” 表示类名,*即所有类
.*(..) 表示任何方法名,括号表示参数,两个点表示任何参数类型

实现方式三 注解实现

xml文件开启注解扫描和支持注解

    <!--开启注解支持-->
    <aop:aspectj-autoproxy/>
    <!--开启注解的支持-->
  <context:component-scan base-package="com.liu.annnoPoincut"/>
    <context:annotation-config/>


    <bean id="log" class="com.liu.log.Log"/>
    <bean id="AfterLog" class="com.liu.log.AfterLog"/>
    <bean id="UserService" class="com.liu.service.UserServiceImpl"/>
    <bean id="diy" class="com.liu.DIY.DiyPioncut"/>

切面类进行bean注册和切点确认

package com.liu.annnoPoincut;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component
@Aspect
//标记这个类是一个切面
public class AnnoPoincut {

    @Before("execution(* com.liu.service.UserServiceImpl.*(..))")
    public void before() {
        System.out.println("---------------执行前");
    }

    @After("execution(* com.liu.service.UserServiceImpl.*(..))")
    public void after() {
        System.out.println("---------------执行后");
    }

}

posted @   小幼虫虫  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示