Spring注解(AOP)

底层动态代理

程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式

导入aop的相关模块

<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.1.6.RELEASE</version>
</dependency>

动态感知业务类运行的状态

通知: 前置 @Before  后置 @After  环绕 @Around 异常@AfterThrowing  返回 @AfterReturning

补充环绕通知: 动态代理,手动推进目标方法运行(joinPoint.proceed() )

步骤:

编写切面类

在切面类里面  把每个方法 何时何地切入都指定好

将切面类和业务逻辑类 都添加到容器中

告诉容器 哪个是切面类@Aspect

在 xml中  <aop: aspectj-autoproxy> </aop:aspectj-autoproxy>    开启基于注解版的切面功能

注解中: 在当前的配置类加入  @EnableAspectJAutoProxy 启用基于注解的aop模式

正常代码:

@Component
public class Mathcalculator {
     public int div(int i , int j) {
         System.out.println("Mathcalculator--div被调用");
         return i/j;
     }
}

切面类:

@EnableAspectJAutoProxy
@Configuration
public class AOPConfig {
   @Bean  //业务逻辑类注册到容器
    public Mathcalculator mathcalculator() {
        return new Mathcalculator();
    }

   @Bean  // 切面类注册到容器中
   public LogAspects logAspects() {
       return new LogAspects();
   }
}

测试:

public class test {
    @Test
    public void test01(){
        //使用无参构造器  创建applicationContext  (详情自己研究下有参构造器的方法)
        AnnotationConfigApplicationContext applicationContext=
                new AnnotationConfigApplicationContext(AOPConfig.class);
        Mathcalculator bean = applicationContext.getBean(Mathcalculator.class);
        bean.div(1, 1);
       //设置需要激活的环境
        applicationContext.getEnvironment().setActiveProfiles("dev","test"); //可以设置多个
       //注册主配置类
        applicationContext.register(Profile.class);
       //启动刷新容器
       applicationContext.refresh();
      }
} 

结果:

升级:

切面类

@Aspect
public class LogAspects {
  //抽取公共的切入点表达式  本类的  如果是别的类的 写全名就OK了

    @Pointcut("execution(public int com.toov5.config.Mathcalculator .*(..))" )
    public void pointCut() {

    }
// @Before("public int com.toov5.config.Mathcalculator.div(int , int)")
   @Before( "pointCut()" )
    public void logStart(JoinPoint joinpoint) {  //获取签名 获取方法
      Object[] args = joinpoint.getArgs(); //目标方法 运行时候需要的参数表
        System.out.println("除法运行@Before"+joinpoint.getSignature().getName()+"运行时参数表"+args );
    }
    @After( "pointCut()" ) //运行异常与否 都要执行的
    public void logEnd(JoinPoint joinPoint) {
        System.out.println(joinPoint.getSignature().getName()+"除法结束@After");
    }
    @AfterReturning(value="pointCut()", returning="result")
    public void logReturn(JoinPoint joinpoint,Object result ) { //result 接受返回值
        System.out.println(joinpoint.getSignature().getName()+"除法正常运行@AfterReturning,结果:"+result);
    }
    @AfterThrowing(value = "pointCut()", throwing="e")
    public void logException(JoinPoint joinpoint, Exception e) {
        System.out.println( joinpoint.getSignature().getName()+"除法异常@AfterThrowing"+e.getMessage());
    }
}

配置:

@EnableAspectJAutoProxy
@Configuration
public class AOPConfig {
   @Bean  //业务逻辑类注册到容器
    public Mathcalculator mathcalculator() {
        return new Mathcalculator();
    }

   @Bean  // 切面类注册到容器中
   public LogAspects logAspects() {
       return new LogAspects();
   }
}

测试类:

public class test {
    @Test
    public void test01(){
        //使用无参构造器  创建applicationContext  (详情自己研究下有参构造器的方法)
        AnnotationConfigApplicationContext applicationContext=
                new AnnotationConfigApplicationContext(AOPConfig.class);
        Mathcalculator bean = applicationContext.getBean(Mathcalculator.class);
        bean.div(1, 1);
       //设置需要激活的环境
        applicationContext.getEnvironment().setActiveProfiles("dev","test"); //可以设置多个
       //注册主配置类
        applicationContext.register(Profile.class);
       //启动刷新容器
       applicationContext.refresh();
      }
} 

结果:

JointPoint 要写一定要写在 参数的首位!

三步走:

1  将业务逻辑组件和切面类都加入到容器,告诉Spring哪个是切面类(@Aspect)

2 在切面类上的每一个通知方法上标注 通知注解,告诉Spring合适何地运行(切入点表达式)

3 开启基于注解的aop模式 与config上

总结:

aop的原理



加入@EnableAspectJAutoProxy  才有AOP

继续点开看

利用AspectJAutoProxyRegistrar  给自定义容器中注册bean

给容器注册一个AnnotationAwareAspectJAutoProxyCreator   自动代理创建器

可以一直追踪其父类:

实现了 SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware

后置处理器

关注后置处理器的工作  Bean初始化完成前后做的事情

BeanFactory                自动注入

AbstractAutoProxyCreator :

@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}

然后是与后置处理器有关的:

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)

有后置处理器的逻辑

原文地址:https://www.cnblogs.com/toov5/p/10667255.html

时间: 2024-10-18 03:45:20

Spring注解(AOP)的相关文章

基于spring注解AOP的异常处理

一.前言 项目刚刚开发的时候,并没有做好充足的准备.开发到一定程度的时候才会想到还有一些问题没有解决.就比如今天我要说的一个问题:异常的处理.写程序的时候一般都会通过try...catch...finally对异常进行处理,但是我们真的能在写程序的时候处理掉所有可能发生的异常吗? 以及发生异常的时候执行什么逻辑,返回什么提示信息,跳转到什么页面,这些都是要考虑到的. 二.基于@ControllerAdvice(加强的控制器)的异常处理 参考文档:http://jinnianshilongnian

spring 注解AOP

 aspectAnnotation的切面信息,加到了AnnotationAwareAspectJAutoProxyCreator的advisorsCache属性里面去了. 解析annotationServiceImpl的时候(此时AspectAnnotation还没有解析),resolveBeforeInstantiation方法里面shouldSkip方法里面,会去spring的容器找所有有Aspect注解的类,找到aspectAnnotation,然后把aspectAnnotation的切面

Spring 注解--AOP篇

切面(advisor) 通知(advice) 切点(pointcut) 连接点(joinpoint) 切面(advisor) 获取切点和通知,用于在初始化bean 时生成代理.切点(pointcut) 定义所需要切的位置通知(advice) 指定切的时机连接点(joinpoint) 把切点和需要切点类给串起来. 在spring中获取到所有的切面,在beanPostPross中去生成代理. https://blog.csdn.net/m0_37962779/article/details/7882

【SSH进阶之路】Spring的AOP逐层深入——采用注解完成AOP(七)

上篇博文[SSH进阶之路]Spring的AOP逐层深入--AOP的基本原理(六),我们介绍了AOP的基本原理,以及5种通知的类型, AOP的两种配置方式:XML配置和Aspectj注解方式. 这篇我们使用注解方式来实现一个AOP,我们先看一下项目的目录. 我们采用的是JDK代理,所以首先将接口和实现类代码附上: package com.tgb.spring; public interface UserManager { public void addUser(String userName,St

8.Spring【AOP】注解方式

1.引入jar包 sprig框架基础包+JUntil整合包+日志包+AOP包 spring的传统AOP的开发的包 spring-aop-4.2.4.RELEASE.jar com.springsource.org.aopalliance-1.0.0.jar aspectJ的开发包 com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar spring-aspects-4.2.4.RELEASE.jar 2.引入配置文件(AOP约束,注解约束) <

spring之aop编程——基于注解、xml配置文件方式

AOP(Aspect Oriented Programming),是面向切面编程的技术.AOP基于IoC基础,是对OOP的有益补充.spring中AOP的配置方式有2种方式:xml配置和AspectJ注解方式. 一.xml配置的方式: 1.service接口和服务类: package cn.edu.nuc.SpringTest.service; public interface DemoService { public String sayHello(String name) ; } packa

Spring入门(二)— IOC注解、Spring测试AOP入门

一.Spring整合Servlet背后的细节 1. 为什么要在web.xml中配置listener <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> 配置listener主要是为了捕获项目发布 | 服务器启动的契机 ,为了解析xml , 创建工厂. 这个listener是spring官方提供

spring注解开发及AOP

Spring的bean管理(注解) 注解介绍 1 代码里面特殊标记,使用注解可以完成功能 2 注解写法 @注解名称(属性名称=属性值) 3 注解使用在类上面,方法上面 和 属性上面 Spring注解开发准备 1 导入jar包 (1)导入基本的jar包 (2)导入aop的jar包 2 创建类,创建方法 3 创建spring配置文件,引入约束 (1)第一天做ioc基本功能,引入约束beans (2)做spring的ioc注解开发,引入新的约束 <beans xmlns:xsi="http://

Spring的AOP基于AspectJ的注解方式开发3

上上偏博客介绍了@Aspect,@Before 上篇博客介绍了spring的AOP开发的注解通知类型:@Before,@AfterThrowing,@After,@AfterReturning,@Around 也介绍了JoinPoint和ProceedingJoinPoint的区别 这篇博客讲@PointCut的使用,切入点注解----转载自https://www.cnblogs.com/ltfxy/p/9885742.html 这种方法便于维护管理 /** * 切面类:注解的切面类 */ @A

spring学习之aspectj的注解aop

基于aspectj的注解aop 1 使用注解方式实现aop操作 第一步 创建对象 第二步 在spring核心配置文件中,开启aop配置 第三步 在增强类上面使用注解完成aop操作 原文地址:https://www.cnblogs.com/czsy/p/10390181.html