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如何使用,如何切换动态代理,如何拿到动态代理的参数,如何获取代理对象。


相关文章
|
1月前
|
SQL 监控 Java
在IDEA 、springboot中使用切面aop实现日志信息的记录到数据库
这篇文章介绍了如何在IDEA和Spring Boot中使用AOP技术实现日志信息的记录到数据库的详细步骤和代码示例。
在IDEA 、springboot中使用切面aop实现日志信息的记录到数据库
|
1月前
|
Java
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
这篇文章是Spring5框架的实战教程,深入讲解了AOP的基本概念、如何利用动态代理实现AOP,特别是通过JDK动态代理机制在不修改源代码的情况下为业务逻辑添加新功能,降低代码耦合度,并通过具体代码示例演示了JDK动态代理的实现过程。
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
|
6天前
|
Java 开发者 数据格式
【Java笔记+踩坑】SpringBoot基础4——原理篇
bean的8种加载方式,自动配置原理、自定义starter开发、SpringBoot程序启动流程解析
【Java笔记+踩坑】SpringBoot基础4——原理篇
|
1月前
|
NoSQL Java Redis
Redis6入门到实战------ 八、Redis与Spring Boot整合
这篇文章详细介绍了如何在Spring Boot项目中整合Redis,包括在`pom.xml`中添加依赖、配置`application.properties`文件、创建配置类以及编写测试类来验证Redis的连接和基本操作。
Redis6入门到实战------ 八、Redis与Spring Boot整合
|
1月前
|
XML Java 数据格式
Spring5入门到实战------11、使用XML方式实现AOP切面编程。具体代码+讲解
这篇文章是Spring5框架的AOP切面编程教程,通过XML配置方式,详细讲解了如何创建被增强类和增强类,如何在Spring配置文件中定义切入点和切面,以及如何将增强逻辑应用到具体方法上。文章通过具体的代码示例和测试结果,展示了使用XML配置实现AOP的过程,并强调了虽然注解开发更为便捷,但掌握XML配置也是非常重要的。
Spring5入门到实战------11、使用XML方式实现AOP切面编程。具体代码+讲解
|
21天前
|
Java API UED
【实战秘籍】Spring Boot开发者的福音:掌握网络防抖动,告别无效请求,提升用户体验!
【8月更文挑战第29天】网络防抖动技术能有效处理频繁触发的事件或请求,避免资源浪费,提升系统响应速度与用户体验。本文介绍如何在Spring Boot中实现防抖动,并提供代码示例。通过使用ScheduledExecutorService,可轻松实现延迟执行功能,确保仅在用户停止输入后才触发操作,大幅减少服务器负载。此外,还可利用`@Async`注解简化异步处理逻辑。防抖动是优化应用性能的关键策略,有助于打造高效稳定的软件系统。
30 2
|
1月前
|
Java Spring 容器
SpringBoot整合AOP实现打印方法执行时间切面
SpringBoot整合AOP实现打印方法执行时间切面
30 1
|
1月前
|
Java API Spring
Spring Boot 中的 AOP 处理
对 Spring Boot 中的切面 AOP 做了详细的讲解,主要介绍了 Spring Boot 中 AOP 的引入,常用注解的使用,参数的使用,以及常用 api 的介绍。AOP 在实际项目中很有用,对切面方法执行前后都可以根据具体的业务,做相应的预处理或者增强处理,同时也可以用作异常捕获处理,可以根据具体业务场景,合理去使用 AOP。
|
21天前
|
JSON Java API
解码Spring Boot与JSON的完美融合:提升你的Web开发效率,实战技巧大公开!
【8月更文挑战第29天】Spring Boot作为Java开发的轻量级框架,通过`jackson`库提供了强大的JSON处理功能,简化了Web服务和数据交互的实现。本文通过代码示例介绍如何在Spring Boot中进行JSON序列化和反序列化操作,并展示了处理复杂JSON数据及创建RESTful API的方法,帮助开发者提高效率和应用性能。
48 0
|
21天前
|
SQL Java 数据库连接
Spring Boot联手MyBatis,打造开发利器:从入门到精通,实战教程带你飞越编程高峰!
【8月更文挑战第29天】Spring Boot与MyBatis分别是Java快速开发和持久层框架的优秀代表。本文通过整合Spring Boot与MyBatis,展示了如何在项目中添加相关依赖、配置数据源及MyBatis,并通过实战示例介绍了实体类、Mapper接口及Controller的创建过程。通过本文,你将学会如何利用这两款工具提高开发效率,实现数据的增删查改等复杂操作,为实际项目开发提供有力支持。
54 0