【Spring】基于注解的AOP编程

44 篇文章 1 订阅
本文详细介绍了Spring AOP开发中的关键步骤,包括原始功能接口实现、额外功能的MyAspect切面、切入点定义、组装切面及切面复用。还讨论了JDK和CGLIB动态代理的区别,并展示了如何在业务方法间灵活应用AOP。
摘要由CSDN通过智能技术生成

一、开发步骤

1 原始功能

public interface UserService {
    void register(User user);
    boolean login(String name, String password);
}
public class UserServiceImpl implements UserService {
    @Override
    public void register(User user) {
        System.out.println("UserServiceImpl.register 业务运算 + DAO");
        // throw new RuntimeException("测试异常");
    }

    @Log
    @Override
    public boolean login(String name, String password) {
        System.out.println("UserServiceImpl.login 业务运算 + DAO");
        return true;
    }
}

2 额外功能
3 切入点
4 组装切面

2、3、4都放在MyAspect内完成。

@Aspect
public class MyAspect {
    @Around("execution(* login(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("---- aspect log ----");
        Object ret = joinPoint.proceed();
        return ret;
    }
}
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="userService" class="com.zqc.aspect.UserServiceImpl"/>
    <!--
        切面:
            1. 额外功能
            2. 切入点啊
            3. 组装切面
    -->
    <bean id="around" class="com.zqc.aspect.MyAspect"/>
    <!--告知 Spring 基于注解进行 AOP 编程-->
    <aop:aspectj-autoproxy/>
</beans>

二、切入点复用

切入点复用:在切面类中定义⼀个函数,上面用 @Pointcut 注解。
通过这种方式定义切入点表达式,后续更加有利于切入点复用。

@Aspect
public class MyAspect {

    @Pointcut("execution(* login(..))")
    public void myPoincut() {}

    @Around(value = "myPoincut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("---- aspect log ----");
        Object ret = joinPoint.proceed();
        return ret;
    }
    @Around(value = "myPoincut()")
    public Object around1(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("---- aspect transaction ----");
        Object ret = joinPoint.proceed();
        return ret;
    }
}

三、切换动态代理创建方式

AOP 底层实现 2 种代理创建方式:

  • JDK:通过 实现接口,做新的实现类 创建代理对象
  • Cglib:通过 继承父类,做新的子类 创建代理对象

默认情况 AOP 编程 底层应用 JDK动态代理创建方式。

基于注解的 AOP 开发 中切换为 Cglib:

<aop:aspectj-autoproxy proxy-target-class="true"/>

传统的 AOP 开发 中切换为 Cglib:

<aop:config proxy-target-class="true">
	...
</aop:config>

四、业务方法互相调用

在同⼀个业务类中,进⾏业务方法间的相互调用,只有最外层的方法,才是加入了额外功能(内部的方法,通过普通的方式调用,都调用的是原始方法)。如果想让内层的方法也调用代理对象的方法,就要实现 AppicationContextAware 获得⼯厂,进而获得代理对象。

public class UserServiceImpl implements UserService, ApplicationContextAware {
    private ApplicationContext ctx;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ctx = applicationContext;
    }
    @Override
    public void register(User user) {
        System.out.println("UserServiceImpl.register 业务运算 + DAO");

        // this.login("zhenyu", "123456"); // 这么写调用的是本类的 login 方法, 即原始对象的 login 方法
        // 为什么不在这里创建一个工厂获取代理对象呢?
        // Spring的工厂是重量级资源, 一个应用中应该只创建一个工厂.
        // 因此我们必须通过 ApplicationContextAware 拿到已经创建好的工厂
        UserService userService = (UserService) ctx.getBean("userService");
        userService.login("yusael", "123456");
    }

    @Override
    public boolean login(String name, String password) {
        System.out.println("UserServiceImpl.login 业务运算 + DAO");
        return true;
    }
}

五、总结

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

望天边星宿

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值