Spring篇—一篇文章带你深入理解Spring中的面向切面AOP,含详细的AOP实现方式!

对AOP的理解

常规情况下我们开发都是围绕框架进行纵向开发,但是如果我们想在原有的基础上增加一些其他的拓展业务,这个时候就需要面向切面将某个业务恒插进去,因此面向切面编程就诞生了!
一、面向切面编程的原理

二、AOP在Spring中的作用
AOP在Spring中提供声明式事务:允许用户自定义切面(自定义拓展业务的类)
AOP中设计的一些关键词:

在Spring中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice(方法):

AOP实现方式(方式一中带有使用AOP的依赖)

实现方式一:使用Spring API接口实现

一、编写service接口

//定义Service接口
public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void select();
}

二、编写接口实现类

public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加用户");
    }

    @Override
    public void delete() {
        System.out.println("删除用户");

    }

    @Override
    public void update() {
        System.out.println("修改用户");

    }

    @Override
    public void select() {
        System.out.println("查询用户");

    }
}

三、编写前后日志增强,注意,在Spring中已经帮我们写好了接口,我们直接实现接口重写方法即可
1、前置日志增强

//前置日志增强:实现MethodBeforeAdvice接口
public class BeforeLog implements MethodBeforeAdvice {

    //method: 要执行的目标对象的方法
    //objects:参数
    //o:目标对象
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println(method.getClass().getName() + "方法的" + method.getName() + "被执行了");
    }
}

2、后置日志增强

//后置日志增强:实现AfterReturningAdvice接口
public class AfterLog implements AfterReturningAdvice {

    //o:返回值
    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("执行了" + method.getName() + "方法,返回结果为:" + o);
    }
}

四、想要实现AOP必须先导入AOP织入依赖

<!-- 想用AOP必须要导入这个依赖 -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>

五、在applicationContext.xml核心配置文件中导入AOP约束

六、applicationContext.xml中注册Bean、配置aop

<!--    注册Bean-->
<bean id="afterLog" class="com.guohui.service.log.AfterLog"/>
<bean id="beforeLog" class="com.guohui.service.log.BeforeLog"/>
<bean id="userService" class="com.guohui.service.UserServiceImpl"/>
<!--    方式一:使用原生的Spring API接口-->
<!--    配置AOP,需要现在上面导入AOP的约束-->
<aop:config>
    <!--        配置切入点,配置将来的方法或者类切入的目标地点,里面要写一个expression表达式:execution(修饰词 返回值 类名 方法名 参数),其中*表示所有的都可以,(..)表示所有的参数-->
    <aop:pointcut id="pointcut" expression="execution(* com.guohui.service.UserServiceImpl.*(..))"/>
    <!--        配置环绕增加,前后日志要用advisor关键字配置到切入点的前后-->
    <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
    <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>

七、测试

public class MyTest {
    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //动态代理,根本是动态代理的接口,所以我们将实现类传进来,但是类型要写接口类型
        UserService userService = (UserService) context.getBean("userService");
        userService.add();
    }
}

八、控制台

九、总结
方式一,首先要将要切入的方法,实现对应的接口(前置或者后置日志增强),在applicationContext.xml中对切入点和环绕增强进行配置,里面的一些关键字和表达式需要记住,最后测试的时候,注意动态代理本质上代理的是接口,所以我们最后通过getBean一定要获得接口类型的对象,调用接口中的方法,才能完成AOP的切入!

实现方式二:自定义实现AOP 自定义切面

一、省略掉了之前中的LogAfter和LogBefore类,直接自定义一个切面类

//自定义切面类
public class DiyPoint {
    //自定义通知:就是类中的方法
    public void before(){
        System.out.println("=======方法执行前========");
    }

    public void after(){
        System.out.println("=======方法执行后========");
    }
}

二、在applicationContext.xml中进行配置切面

<!--    方式二:自定义类实现AOP切入-->

<!--    注册自定义的切面类-->
<bean id="diy" class="com.guohui.diy.DiyPoint"/>

<!--    配置切面-->
<aop:config>
    <!--        自定义切面,ref:表示引用的类-->
    <aop:aspect ref="diy">
        <!--            配置切入点,用来标记切入的方法的目标位置-->
        <aop:pointcut id="pointcut" expression="execution(* com.guohui.service.UserServiceImpl.*(..))"/>
        <!--            切入点之前执行的方法,method要写自定义切面中的通知(即方法),pointcut-ref表示要切入的目标点-->
        <aop:before method="before" pointcut-ref="pointcut"/>
        <!--            切入点之后执行的方法,method要写自定义切面中的通知(即方法),pointcut-ref表示要切入的目标点-->
        <aop:after method="after" pointcut-ref="pointcut"/>
    </aop:aspect>
</aop:config>

三、测试

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //动态代理,根本是动态代理的接口,所以我们将实现类传进来,但是类型要写接口类型
        UserService userService = (UserService) context.getBean("userService");
        userService.add();
    }
}

四、控制台

五、总结
使用方式二,可以不用实现过多的接口就可以是现在切入点前后增加方法,只需要自定义切面类,在applicationContext.xml中对切入点和切面以及通知(即切面中的方法)进行配置即可。

实现方式三:注解实现AOP

一、运用注解自定义切面类
用到的注解是@Aspect

//方式三:使用注解实现AOP
//注解@Aspect就是将该类标记成一个切面类
@Aspect
public class AnnotationPointCut {

    //自定义方法前增强,用@Before,里面的参数就是切入点的表达式execution
    @Before("execution(* com.guohui.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("======方法执行前======");
    }
    //方法后置增强
    @After("execution(* com.guohui.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("======方法执行后======");
    }
    //环绕增强
    @Around("execution(* com.guohui.service.UserServiceImpl.*(..))")
    public void around(){

    }
}

二、在applicationContext.xml核心配置文件中对切面类进行注册,并且开启注解支持

<!--    方式三:使用注解实现AOP-->
<!--    注册自定义的注解切面类-->
<bean id="annotationPointCut" class="com.guohui.diy.AnnotationPointCut"/>
<!--    开启注解支持,区别于spring注解开发的注解支持"<context:annotation-config/>"
这里直接导入<aop:aspectj-autoproxy/>即开启了注解支持
-->
<aop:aspectj-autoproxy/>


三、测试

public class MyTest {
    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //动态代理,根本是动态代理的接口,所以我们将实现类传进来,但是类型要写接口类型
        UserService userService = (UserService) context.getBean("userService");
        userService.add();
    }
}

四、控制台

五、总结
注解的使用,简化了配置文件或者实现接口的开发方式,代码简洁明了,不过这三种的实现方式都是基于动态代理的模式,代理接口拓展业务,注解开发也不是很完美,我们需要在每个通知(切面类中的方法)上都要写好切入点的表达式,比较繁琐,现在开发中一般使用方式二或者方式三,仁者见仁智者见智!

至此,你已经深刻的掌握了关于Spring中的AOP思想以及怎么使用AOP,后续会继续更新关于Spring的技术栈,欢迎交流和指正!

  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Be explorer

若认可笔者文章,手头富裕望支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值