java使用spring aop切面编程

7 篇文章 0 订阅
本文详细介绍了面向切面编程(AOP)的概念,包括切面、切入点、连接点、通知等核心概念,并通过实例展示了Spring AOP的使用方法,包括@Aspect注解的切面定义、通知类型以及配置。此外,还探讨了AOP的原理,如EnableAspectJAutoProxy注解的作用以及代理的创建过程。最后,提到了Spring中实现代码增强的多种方式。
摘要由CSDN通过智能技术生成

aop概念

1、切面(Aspect)
首先要理解‘切’字,需要把对象想象成一个立方体,传统的面向对象变成思维,类定义完成之后(封装)。每次实例化一个对象,对类定义中的成员变量赋值,就相当于对这个立方体进行了一个定义,定义完成之后,那个对象就在那里,不卑不亢,不悲不喜,等着被使用,等着被回收。

面向切面编程则是指,对于一个我们已经封装好的类,我们可以在编译期间或在运行期间,对其进行切割,把立方体切开,在原有的方法里面添加(织入)一些新的代码,对原有的方法代码进行一次增强处理。而那些增强部分的代码,就被称之为切面,一般用于通用日志处理代码、事务处理、权限认证等等。

2、切入点(PointCut)
要对哪些类中的哪些方法进行增强,进行切割,指的是被增强的方法。即要切哪些东西。

3、连接点(JoinPoint)
我们知道了要切哪些方法后,剩下的就是什么时候切,在原方法的哪一个执行阶段加入增加代码,这个就是连接点。如方法调用前,方法调用后,发生异常时等等。

4、通知(Advice)
通知被织入方法,改如何被增强。定义切面的具体实现。那么这里面就涉及到一个问题,空间(切哪里)和时间(什么时候切,在何时加入增加代码),空间我们已经知道了就是切入点中定义的方法,而什么时候切,则是连接点的概念,如下面实例中,通用日志处理(切面),@Pointcut规则中指明的方法即为切入点,@Before、@After是连接点,而下面的代码就是对应通知。

5、目标对象(Target Object)
被一个或多个切面所通知的对象,即为目标对象。

6、AOP代理对象(AOP Proxy Object)
AOP代理是AOP框架所生成的对象,该对象是目标对象的代理对象。代理对象能够在目标对象的基础上,在相应的连接点上调用通知。

7、织入(Weaving)
将切面切入到目标方法之中,使目标方法得到增强的过程被称之为织入。

 

aop使用方法

一、引入依赖

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
        </dependency>
        <dependency>

二、定义一个切面类

@Aspect
@Component
public class MyAspect {
    /**
     * 声明切入点
     * 该方法 point 的内容并不重要,方法名也不重要,实际上它只是作为一个标识,供通知使用
     */
    @Pointcut("execution(* com.example.demo.web.Demo.hello(..))")
    void point(){}
    /**
     * 目标方法调用之前调用
     */
    @Before("point()")//也可直接使用execution(* com.example.demo.web.Demo.hello(..)),声明切入点,只是
    public void before() {
        System.out.println("before ...");
    }
    /**
     * 目标方法返回或异常之后调用
     */
    @After("point()")
    public void after() {
        System.out.println("After ...");
    }
    /**
     * 目标方法返回之后调用
     */
    @AfterReturning("point()")
    public void afterReturning() {
        System.out.println("AfterReturning ...");
    }
    /**
     * 目标方法抛出异常之后调用
     */
    @AfterThrowing("point()")
    public void afterThrowing() {
        System.out.println("AfterThrowing ...");
    }
    /**
     * 目标方法调用之后调用
     */
    @Around("point()")
    public void around(ProceedingJoinPoint pj) {
        try {
            System.out.println("Around aaa ...");
            pj.proceed();//如果不调用该对象的 proceed() 方法,表示不调用原目标方法及上面的切面方法
            System.out.println("Around bbb ...");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }
}

三、增加配置@EnableAspectJAutoProxy注解(可以不做),因为springboot-autoconfiguration中已经有此注解

@SpringBootApplication
@EnableAspectJAutoProxy(proxyTargetClass = true)//proxyTargetClass为true说明走CGLIB代理,否则走JDK代理
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

 springboot-autoconfiguration代码如下:

  

如果要修改proxy-target-class还可以通过配置文件配置

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

 

 aop原理

1、EnableAspectJAutoProxy注解引入了AspectJAutoProxyRegistrar处理类

2、AspectJAutoProxyRegistrar类注册bean定义

3、在 AopConfigUtils.forceAutoProxyCreatorToUseClassProxying方法里标记上此类需要代理

 4、在spring注册bean时增加代理

下图是在AbstractAutoProxyCreator类的wrapIfNecessary方法中
 

 下图是spring创建bean时的栈帧

在CglibAopProxy类中创建代理 

真正被增加的类会执行DynamicAdvisedInterceptor类的intercept方法

 之后的每次被拦截的方法都会执行intercept方法

 

 

ProxyFactory类

是spring对两种动态代理Proxy和cglib进行的封装

 

 

spring中代理实现代码增强几种方式

  1. @Aspect注解
  2. ProxyFactoryBean(是一个FactoryBean)
  3. 编程方式注入advisor。

 

 

Spring Boot中定义一个切面,你可以按照以下步骤进行操作: 1. 创建一个Java类,并使用`@Aspect`注解标记该类为切面类。 2. 在切面类中,定义切入点(Pointcut),用于确定哪些方法需要被拦截。你可以使用`@Pointcut`注解来定义切入点表达式,例如`@Pointcut("execution(* com.example.*.*(..))")`表示拦截com.example包下的所有方法。 3. 在切面类中,编通知(Advice)方法,用于定义具体的拦截逻辑。通知可以分为前置通知(Before),后置通知(After),返回通知(AfterReturning),异常通知(AfterThrowing)和环绕通知(Around)等类型。 4. 使用`@Before`、`@After`、`@AfterReturning`、`@AfterThrowing`或`@Around`等注解标记对应的通知方法。这些注解表示在切入点的不同位置执行相应的逻辑。 5. 在Spring Boot的配置类中,使用`@EnableAspectJAutoProxy`注解开启自动代理功能,以便让切面生效。 以下是一个简单的示例: ```java import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Aspect @Component public class MyAspect { @Pointcut("execution(* com.example.*.*(..))") public void myPointcut() { } @Before("myPointcut()") public void beforeAdvice() { System.out.println("Before method execution"); } @After("myPointcut()") public void afterAdvice() { System.out.println("After method execution"); } } ``` 在上述示例中,切面类`MyAspect`使用`@Aspect`和`@Component`注解进行标记。`myPointcut()`方法定义了一个切入点,表示拦截com.example包下的所有方法。`beforeAdvice()`方法使用`@Before`注解标记,表示在拦截的方法执行前执行逻辑。`afterAdvice()`方法使用`@After`注解标记,表示在拦截的方法执行后执行逻辑。 最后,在Spring Boot的配置类中添加`@EnableAspectJAutoProxy`注解,启用自动代理功能: ```java import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration @EnableAspectJAutoProxy public class AppConfig { } ``` 通过以上步骤,你就成功地在Spring Boot应用中定义了一个切面。当满足定义的切入点条件时,切面中的通知方法将被触发执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值