spring框架 aop:aspectj-autoproxy proxy-target-class=“true“用法理解

简介: spring框架 aop:aspectj-autoproxy proxy-target-class=“true“用法理解

一、场景描述

在spring框架中,集成使用AOP面向切面编程:
1、当一个类有接口的时候,那么spring默认使用的是JDK动态代理
2、如果当前类没有接口的时候,那么spring会默认使用CGLIB动态代理
3、如果一个类有接口的时候,还想要使用CGLIB动态代理,
那么就需要在spring的配置文件中加上 :
aop:aspectj-autoproxy proxy-target-class="true" 属性。

二、分别进行代码演示

先准备公共代码

切面类:MyAspect 
package com.ba01;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import java.util.Date;
@Aspect
public class MyAspect {
    @Around(value = "mypt()")
    public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Object object = null;
        System.out.println("环绕通知,在目标方法之前调用,输出时间," + new Date());
        //1、可以控制目标方法的执行
        String name = "";
        Object[] args = joinPoint.getArgs();
        if(args != null && args.length > 1){
            name = (String) args[0];
        }
        if(!"zhangshan".equals(name)){
            //2、目标方法的调用
            object = joinPoint.proceed();//相当于method.invoke();
        }
        System.out.println("环绕通知,在目标方法之后调用,输出时间," + new Date());
        //3、可以直接修改方法的返回值
        object = "1234werqwe";
        return object;
    }
    @AfterThrowing(value = "execution(* *(..))",throwing = "ex")
    public void myafterThrowing(Exception ex){
        System.out.println("异常通知:" + ex.getMessage());
        //可以发送邮件,短信,来通知开发人员
    }
    @Before(value = "mypt())")
    public void myafterThrowing(){
        System.out.println("前置通知:");
    }
    @Pointcut(value = "execution(* *(..))")
    private void mypt(){
    }
}

1、当一个类有接口的时候,那么spring默认使用的是JDK动态代理

接口SomeService 
public interface SomeService {
    public void doSome(String name,Integer age);
    public String doOther(String name,Integer age);
}

接口实现类SomeServiceImpl

package com.ba01;
import com.ba01.SomeService;
import org.springframework.stereotype.Component;
public class SomeServiceImpl implements SomeService{
    @Override
    public String doOther(String name, Integer age) {
        System.out.println("====doOther方法===========");
        return "abcd";
    }
    @Override
    public void doSome(String name, Integer age) {
        System.out.println("====dosome方法===========");
    }
}
spring的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
       http://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">
    <!--声明目标对象-->
    <bean id="someService" class="com.ba01.SomeServiceImpl"/>
    <!--声明切面类对象-->
    <bean id="myAspect" class="com.ba01.MyAspect"/>
    <!--声明自动代理生成器
        aspectj-autoproxy:会把spring 容器中所有的目标对象,一次性的生成代理对象
    -->
    <aop:aspectj-autoproxy/>
</beans>
执行测试类,主要就是把获得的bean对象打印出来
@Test
    public void shouldAnswerWithTrue()
    {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        SomeService someService =  (SomeService) context.getBean("someService");
        System.out.println(someService.getClass());
    }

输出结果,代表是使用的是DK动态代理

class com.sun.proxy.$Proxy14
Process finished with exit code 0

2、如果当前类没有接口的时候,那么spring会默认使用CGLIB动态代理

去掉实现类的接口,直接为普通的类

public class SomeServiceImpl{
    public String doOther(String name, Integer age) {
        System.out.println("====doOther方法===========");
        return "abcd";
    }
    public void doSome(String name, Integer age) {
        System.out.println("====dosome方法===========");
    }
}
切面类不变,spring的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
       http://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">
    <!--声明目标对象-->
    <bean id="someService" class="com.ba01.SomeServiceImpl"/>
    <!--声明切面类对象-->
    <bean id="myAspect" class="com.ba01.MyAspect"/>
    <!--声明自动代理生成器
        aspectj-autoproxy:会把spring 容器中所有的目标对象,一次性的生成代理对象
    -->
    <aop:aspectj-autoproxy/>
</beans>
直接运行测试类,注意此时是用的SomeServiceImpl ,而不是接口SomeService
@Test
    public void shouldAnswerWithTrue()
    {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        SomeServiceImpl someService =  (SomeServiceImpl) context.getBean("someService");
        System.out.println(someService.getClass());
    }
运行结果,我们发现现在变成了CGLIB动态代理,这个是spring框架自动帮我们实现的
class com.ba01.SomeServiceImpl$$EnhancerBySpringCGLIB$$4ec165aa
Process finished with exit code 0

3、如果一个类有接口的时候,还想要使用CGLIB动态代理

修改spring的xml文件
<beans>
...
<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>

实现类还是加上对接口的实现

public class SomeServiceImpl implements SomeService{
    @Override
    public String doOther(String name, Integer age) {
        System.out.println("====doOther方法===========");
        return "abcd";
    }
    @Override
    public void doSome(String name, Integer age) {
        System.out.println("====dosome方法===========");
    }
}
测试类泡一下
@Test
    public void shouldAnswerWithTrue()
    {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        SomeService someService =  (SomeService) context.getBean("someService");
        System.out.println(someService.getClass());
    }

运行结果,此时虽然有实现接口,但是spring默认使用了CGLIB动态代理

class com.ba01.SomeServiceImpl$$EnhancerBySpringCGLIB$$63108b69
Process finished with exit code 0


相关文章
|
4月前
|
安全 Java Ruby
我尝试了所有后端框架 — — 这就是为什么只有 Spring Boot 幸存下来
作者回顾后端开发历程,指出多数框架在生产环境中难堪重负。相比之下,Spring Boot凭借内置安全、稳定扩展、完善生态和企业级支持,成为构建高可用系统的首选,真正经受住了时间与规模的考验。
377 2
|
4月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
576 0
|
3月前
|
安全 前端开发 Java
《深入理解Spring》:现代Java开发的核心框架
Spring自2003年诞生以来,已成为Java企业级开发的基石,凭借IoC、AOP、声明式编程等核心特性,极大简化了开发复杂度。本系列将深入解析Spring框架核心原理及Spring Boot、Cloud、Security等生态组件,助力开发者构建高效、可扩展的应用体系。(238字)
|
5月前
|
XML JSON Java
Spring框架中常见注解的使用规则与最佳实践
本文介绍了Spring框架中常见注解的使用规则与最佳实践,重点对比了URL参数与表单参数的区别,并详细说明了@RequestParam、@PathVariable、@RequestBody等注解的应用场景。同时通过表格和案例分析,帮助开发者正确选择参数绑定方式,避免常见误区,提升代码的可读性与安全性。
|
3月前
|
XML Java 数据格式
《深入理解Spring》:AOP面向切面编程深度解析
Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
|
3月前
|
消息中间件 缓存 Java
Spring框架优化:提高Java应用的性能与适应性
以上方法均旨在综合考虑Java Spring 应该程序设计原则, 数据库交互, 编码实践和系统架构布局等多角度因素, 旨在达到高效稳定运转目标同时也易于未来扩展.
186 8
|
4月前
|
监控 Kubernetes Cloud Native
Spring Batch 批处理框架技术详解与实践指南
本文档全面介绍 Spring Batch 批处理框架的核心架构、关键组件和实际应用场景。作为 Spring 生态系统中专门处理大规模数据批处理的框架,Spring Batch 为企业级批处理作业提供了可靠的解决方案。本文将深入探讨其作业流程、组件模型、错误处理机制、性能优化策略以及与现代云原生环境的集成方式,帮助开发者构建高效、稳定的批处理系统。
553 1
|
5月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
6月前
|
安全 Java 微服务
Java 最新技术和框架实操:涵盖 JDK 21 新特性与 Spring Security 6.x 安全框架搭建
本文系统整理了Java最新技术与主流框架实操内容,涵盖Java 17+新特性(如模式匹配、文本块、记录类)、Spring Boot 3微服务开发、响应式编程(WebFlux)、容器化部署(Docker+K8s)、测试与CI/CD实践,附完整代码示例和学习资源推荐,助你构建现代Java全栈开发能力。
752 0

热门文章

最新文章