springboot2原理实战(17)--aop开发必知必会

简介: springboot2原理实战(17)--aop开发必知必会

目录


本文的主要内容如下:

1dc618a0ed9580ce8bfa6facb208c08f.png


一、使用aop小demo认识开发流程


1:spring-boot-start-aop 加入依赖,默认开启了Aop的支持


 

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>


写个被切入的类:


@Repository
public class UserDao {
    public void add(String username, String password){
        System.out.println("add 【username:"+username+",password:"+password+"】");
    }
}


2:写一个Aspect,封装横切关注点(日志,监控等待),需要配置前置通知,后置通知等待,和切入点,哪些包的哪些类的方法等等


这个Aspect需要@Component纳入到spring容器管理,并且需要纳入spring管理:


@Aspect

@Component
public class LogAspect {
    @Before("execution(* com.springboot.demo17.dao..*.*(..))")
    public void log(){
//        System.out.println("before method log done "+ AopContext.currentProxy().getClass());
        System.out.println("before method log done");
    }
 }


3.测试:


@SpringBootApplication
public class Demo17Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Demo17Application.class, args);
        System.out.println(context.getBean(UserDao.class).getClass());
        context.getBean(UserDao.class).add("admin","123");
        context.close();
    }


运行结果:


5d4c6812c8535adbb050f4ddf2e1bce8.png

显示aop已经生效。


二、了解springboot的代理和切换代理操作


看下aop自动配置的类:

46a9d80a6e05e4e3b19d57a0ee70bcdf.png


通过源码,我们可以看到,


1.spring.aop", name = “auto”, havingValue = “true”,说明springboot默认为我们开启Aop我们可以通过这个spring.auto来设置是否开启关闭。


2.springboot2默认是使用的cglib代理。我们可以使用spring.aop.proxy-target-class的true和fasle,来切换代理模式是cglib还是jdk动态代理。true代表cglib,false代表jdk动态代理。


1.默认的动态代理cglib


刚才的aop入门小demo的控制台打印看下:

1dc618a0ed9580ce8bfa6facb208c08f.png

这里也说明我们的确是使用的cglib


2.切换成jdk动态代理


我们知道jdk动态代理是面向接口的,现在设置下:


写一个接口:


public interface IuserDao {
    public void add(String username, String password);
}


@Repository


public class UserDao implements IuserDao{
    public void add(String username, String password){
        System.out.println("add 【username:"+username+",password:"+password+"】");
    }
}


配置文件修改动态代理方式:


spring.aop.auto=true
spring.aop.proxy-target-class=false


打印查看:


@SpringBootApplication
public class Demo17Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Demo17Application.class, args);
        System.out.println(context.getBean(UserDao.class).getClass());
        //
        context.getBean(UserDao.class).add("admin","123");
        context.close();
    }
}


测试类:


@SpringBootApplication
public class Demo17Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Demo17Application.class, args);
        //得用接口获取对象
        System.out.println(context.getBean(IuserDao.class).getClass());
        context.getBean(IuserDao.class).add("admin","123");
        context.close();
    }
}


运行,控制台打印:


1dc618a0ed9580ce8bfa6facb208c08f.png

显示已经是java的jdk动态代理了。


特别注意: UserDao必须实现个IUserDao的接口,必须通过接口获取实例,不然使用的还是cglib动态代理。


三、使用aop获取切面参数


拿到切面里面的类或者参数,可以通过JoinPoint point

5d4c6812c8535adbb050f4ddf2e1bce8.png

这里有上面几个方法,可以通过getTarget获取类,getArgs获取方法的参数,getSignature().获取方法名称。


测试下:


改下编织类,添加个after后置织入:


@Aspect
@Component
public class LogAspect {
    @Before("execution(* com.springboot.demo17.dao..*.*(..))")
    public void log(){
//        System.out.println("before method log done "+ AopContext.currentProxy().getClass());
        System.out.println("before method log done");
    }
    @After("execution(* com.springboot.demo17.dao..*.*(..))")
    public void logAfter(JoinPoint point){
        System.out.println("after method log done"+point.getTarget().getClass()+",args="+ Arrays.asList(point.getArgs())+",method="+point.getSignature().getName());
    }
}


测试:


@SpringBootApplication
public class Demo17Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Demo17Application.class, args);
        System.out.println(context.getBean(UserDao.class).getClass());
        //
        context.getBean(UserDao.class).add("admin","123");
        context.close();
    }
}


运行入口函数,控制台打印:


1dc618a0ed9580ce8bfa6facb208c08f.png

显示切面里面的类和参数和方法名都已经获取到了。


四、EnableAspectJAutoProxy获取代理对象


看下这个类的源码:

5d4c6812c8535adbb050f4ddf2e1bce8.png


有2个属性:


proxyTargetClass: 这个属性也可以切换动态代理方式,true代表cglib,false是jdk动态代理


exposeProxy: 这个属性设置为true可以获取到代理对象是谁。

设置为true,可以获取到AopContext对象:

1dc618a0ed9580ce8bfa6facb208c08f.png


现在测试下:

修改织入类:


@Aspect
@Component
public class LogAspect {
    @Before("execution(* com.springboot.demo17.dao..*.*(..))")
    public void log(){
        System.out.println("before method log done "+ AopContext.currentProxy().getClass());
        System.out.println("before method log done");
    }
 }


入口函数,设置可获取代理对象:@EnableAspectJAutoProxy(exposeProxy = true):


@EnableAspectJAutoProxy(exposeProxy = true)
@SpringBootApplication
public class Demo17Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Demo17Application.class, args);
        System.out.println(context.getBean(UserDao.class).getClass());
        //
        context.getBean(UserDao.class).add("admin","123");
        context.close();
    }
}


运行,控制台打印如下:


5d4c6812c8535adbb050f4ddf2e1bce8.png

可以看到,代理对象是:EnhancerBySpringCGLIB.


本文,主要讲laop如何使用,如何切换动态代理,如何拿到动态代理的参数,如何获取代理对象。


相关文章
|
11天前
|
缓存 Java Sentinel
Springboot 中使用 Redisson+AOP+自定义注解 实现访问限流与黑名单拦截
Springboot 中使用 Redisson+AOP+自定义注解 实现访问限流与黑名单拦截
|
7天前
|
安全 Java 测试技术
Spring Boot集成支付宝支付:概念与实战
【4月更文挑战第29天】在电子商务和在线业务应用中,集成有效且安全的支付解决方案是至关重要的。支付宝作为中国领先的支付服务提供商,其支付功能的集成可以显著提升用户体验。本篇博客将详细介绍如何在Spring Boot应用中集成支付宝支付功能,并提供一个实战示例。
25 2
|
7天前
|
Java 关系型数据库 数据库
Spring Boot多数据源及事务管理:概念与实战
【4月更文挑战第29天】在复杂的企业级应用中,经常需要访问和管理多个数据源。Spring Boot通过灵活的配置和强大的框架支持,可以轻松实现多数据源的整合及事务管理。本篇博客将探讨如何在Spring Boot中配置多数据源,并详细介绍事务管理的策略和实践。
31 3
|
6天前
|
Java 调度 Maven
Springboot实战篇--Springboot框架通过@Scheduled实现定时任务
Spring Boot的Scheduled定时任务无需额外Maven依赖,通过`@EnableScheduling`开启。任务调度有两种方式:fixedRate和fixedDelay,前者任务结束后立即按设定间隔执行,后者在任务完成后等待设定时间再执行。更灵活的是cron表达式,例如`0 0 3 * * ?`表示每天3点执行。实现定时任务时,需注意默认单线程执行可能导致的任务交错,可通过自定义线程池解决。
|
6天前
|
XML Java API
Spring Boot 整合 LiteFlow 规则引擎:概念与实战
【4月更文挑战第30天】在现代软件开发中,规则引擎允许我们以声明式的方式定义业务逻辑和决策路径。LiteFlow 是一个轻量级、易于使用的组件式规则引擎,它可以与 Spring Boot 应用无缝整合。本文将介绍如何在 Spring Boot 项目中引入 LiteFlow,实现灵活的业务流程管理。
20 0
|
6天前
|
开发框架 Java Maven
SpringBoot-Starter 概念与实战
【4月更文挑战第30天】Spring Boot 是一个基于 Spring Framework 的开发框架,旨在简化 Spring 应用程序的搭建和开发。Spring Boot 提供了大量的 Starter(启动器)来简化项目的依赖管理和配置,其中最为常见的是 SpringBoot-Starter。
23 1
|
7天前
|
安全 Java 测试技术
利用Java反射机制提高Spring Boot的代码质量:概念与实战
【4月更文挑战第29天】Java反射机制提供了一种强大的方法来在运行时检查或修改类和对象的行为。在Spring Boot应用中,合理利用反射可以提高代码的灵活性和可维护性。本篇博客将探讨Java反射的核心概念,并展示如何通过反射提高Spring Boot项目的代码质量。
23 0
|
7天前
|
监控 Java 测试技术
Spring Boot与事务钩子函数:概念与实战
【4月更文挑战第29天】在复杂的业务逻辑中,事务管理是确保数据一致性和完整性的关键。Spring Boot提供了强大的事务管理机制,其中事务钩子函数(Transaction Hooks)允许开发者在事务的不同阶段插入自定义逻辑。本篇博客将详细探讨事务钩子函数的概念及其在Spring Boot中的应用。
21 1
|
7天前
|
安全 Java 数据安全/隐私保护
Spring Boot优雅实现多租户架构:概念与实战
【4月更文挑战第29天】在多租户系统中,一个应用实例服务于多个租户,每个租户享有独立的数据视图,而应用的基础设施被共享。这样的架构不仅优化了资源使用,还能降低维护和运营成本。本文将详细介绍如何在Spring Boot中实现多租户架构,并提供具体的实战案例。
29 2
|
7天前
|
前端开发 Java 数据安全/隐私保护
Spring Boot使用拦截器:概念与实战
【4月更文挑战第29天】拦截器(Interceptors)在Spring Boot应用中常用于在请求处理的前后执行特定的代码,如日志记录、认证校验、权限控制等。本篇博客将详细介绍Spring Boot中拦截器的概念及其实战应用,帮助开发者理解和利用拦截器来增强应用的功能。
17 0