做Java后端好几年,每天都在跟Spring打交道。而我们都知道Spring的AOP,但是底层的原理我们需要好好去看代码深究。

先来看我这里基于Spring注解驱动开发的aop的例子。

定义一个简单的切面类(至于切面表达式这里不多讲,网上很多)

@Component
@Aspect
public class MyAopTest {
@Pointcut("execution(public * com.kuhn.spring.component.PersonService.*(..))")
public void recordLog(){}
@Before("recordLog()")
public void startMd(){
System.out.println("开始调用方法");
}
}

配置类(ComponentScan 扫描的就是切面类所在的包,这里我直接把我需要业务对象直接Import进来,并在配置类中加入

EnableAspectJAutoProxy注解;)

@Configuration
@Import(PersonService.class)
@ComponentScan(value="com.kuhn.spring.aop")
@EnableAspectJAutoProxy
public class AopConfig {}

main方法test启动类

public class AopText {@org.junit.Testpublic void aoptest(){AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(AopConfig.class);PersonService personService= (PersonService) annotationConfigApplicationContext.getBean(PersonService.class);personService.getPersonService();}
}

结果:

Connected to the target VM, address: '127.0.0.1:51508', transport: 'socket'
五月 18, 2019 4:24:37 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5c03bf22: startup date [Sat May18 16:24:37 CST 2019]; root of context hierarchy
开始调用方法
Disconnected from the target VM, address: '127.0.0.1:51508', transport: 'socket'

这里我们简单的实现了一个前置通知。那么要了解aop原理,源码切入点便是上面配置类中EnableAspectJAutoProxy

注解,这个注解式表示开启aop;那么我们进入这个注解附上源码:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AspectJAutoProxyRegistrar.class})public @interface EnableAspectJAutoProxy {boolean proxyTargetClass() default false;boolean exposeProxy() default false;
}

我们看到在这个接口给容器中注入了AspectJAutoProxyRegistrar 切面自动代理创建器。我们进入这个类,

package org.springframework.context.annotation;import org.springframework.aop.config.AopConfigUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {AspectJAutoProxyRegistrar() {}public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);if(enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}if(enableAspectJAutoProxy.getBoolean("exposeProxy")) {AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);}}
}

我们看到这个类实现ImportBeanDefinitionRegistrar 接口,这个接口是给容器自定义注入对象;

我门进入这个方法

    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, (Object)null);}

进入

   public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);}

进入

    private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");if(registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {BeanDefinition beanDefinition1 = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");if(!cls.getName().equals(beanDefinition1.getBeanClassName())) {int currentPriority = findPriorityForClass(beanDefinition1.getBeanClassName());int requiredPriority = findPriorityForClass(cls);if(currentPriority < requiredPriority) {beanDefinition1.setBeanClassName(cls.getName());}}return null;} else {RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);beanDefinition.setSource(source);beanDefinition.getPropertyValues().add("order", Integer.valueOf(-2147483648));beanDefinition.setRole(2);registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);return beanDefinition;}}

这里我们看到这个方法往BeanDefinitionRegistry 注册了AnnotationAwareAspectJAutoProxyCreator这个组件。到这里我们容器中就

有AnnotationAwareAspectJAutoProxyCreator。我们只要了解这个组件是怎么得工作的,那么我们就理解了aop的工作原理。 那么我们来看一下这个对象的关系结构

我们看到AnnotationAwareAspectJAutoProxyCreator继承了ProxyProcessorSupport,实现了BeanFactoryAware和SmartInstantiationAwareBeanPostProcessor。所以我们看到它的父类里有一个bean的后置处理器(bean初始化前后完成的事情),和一个bean工厂。

好!我们后面重点关注SmartInstantiationAwareBeanPostProcessor和BeanFactoryAware。

spring aop原理_源码解析Spring的AOP原理(一)相关推荐

  1. 【Spring Boot实战】源码解析Spring Boot自动配置原理

    一.简介 Spring致力于让Java开发更简单,SpringBoot致力于让使用Spring进行Java开发更简单,SpringCloud致力于基于SpringBoot构建微服务生态圈,让微服务开发 ...

  2. 【特征匹配】ORB原理与源码解析

    相关 : Fast原理与源码解析 Brief描述子原理与源码解析 Harris原理与源码解析 http://blog.csdn.net/luoshixian099/article/details/48 ...

  3. PCA-SIFT原理及源码解析

    相关: SIFT原理与源码解析 SURF原理与源码解析 ORB原理与源码解析 FAST原理与源码解析 BRIEF描述子原理与源码解析 Harris原理与源码解析 转载请注明出处:http://blog ...

  4. Spring Boot 核心原理与源码解析 - 目录

    准备重新写 SpringBoot 配置文件解析原理 , 先在这里把要写的内容记下来 Spring Boot 核心原理与源码解析 - 目录 1\何时解析\如何解析 application.propert ...

  5. Spring源码深度解析(郝佳)-学习-源码解析-Spring MVC(三)-Controller 解析

    在之前的博客中Spring源码深度解析(郝佳)-学习-源码解析-Spring MVC(一),己经对 Spring MVC 的框架做了详细的分析,但是有一个问题,发现举的例子不常用,因为我们在实际开发项 ...

  6. spring 注解试事物源码解析

    spring 注解试事物源码解析 基于xml注解式事务入口 public class TxNamespaceHandler extends NamespaceHandlerSupport {stati ...

  7. Spring事件机制Event源码解析(未完待续)

    Spring事件机制Event源码解析(未完待续) 监听器: ApplicationEvent事件 ApplicationListener监听器(观察者) ApplicationEventMultic ...

  8. SpringMVC工作原理及源码解析

    SpringMVC工作原理及源码解析 一:SpringMVC原理图 二:SpringMVC的主要组件 1.前端控制器DispatcherServlet: 2.处理器映射器HandlerMapping: ...

  9. Redis进阶- Redisson分布式锁实现原理及源码解析

    文章目录 Pre 用法 Redisson分布式锁实现原理 Redisson分布式锁源码分析 redisson.getLock(lockKey) 的逻辑 redissonLock.lock()的逻辑 r ...

  10. php 框架源码分析,Laravel框架源码解析之模型Model原理与用法解析

    本文实例讲述了Laravel框架源码解析之模型Model原理与用法.分享给大家供大家参考,具体如下: 前言 提前预祝猿人们国庆快乐,吃好.喝好.玩好,我会在电视上看着你们. 根据单一责任开发原则来讲, ...

最新文章

  1. vue 手写一个时间选择器
  2. c语言字符串的一个简单例子,把一个字符串中的小写字母改成大写字母
  3. [XSS神器]XssEncode chrome插件 - 0x_Jin
  4. 准备重新回归信息安全产业
  5. 080520 雨 大风
  6. 有道词典使用离线翻译
  7. 《数据结构复习》扩展线性链表的广义表
  8. openlayers示例教程002:简析EPSG:4326 和 EPSG: 3857
  9. ORACLE 中利用推理逻辑去算 上年同期 ,注意:ORACLE中查询条件是带有推理逻辑功能的,及oracle中的推理逻辑
  10. 大数据时代下的网络安全与数据隐私论文
  11. 【错误记录】Google Play 上架报错 ( 此版本不符合 Google Play 关于提供 64 位版本应用的要求。| 如果提供 x86 架构动态库则必须提供 x86_64 架构的动态库 )
  12. [深度学习论文笔记]UCTransNet:从transformer的通道角度重新思考U-Net中的跳跃连接
  13. U盘出现物理故障都有哪些表现
  14. 万字详解什么是生成对抗网络GAN
  15. 2019年第八届java B组蓝桥杯省赛真题
  16. 外网如何访问内网/局域网网站【内网穿透】
  17. FPGA——SPI总线控制flash(1)(含代码)
  18. 农业虫害识别相关论文——调研整理
  19. leetcode 1646
  20. python教程app攻略_一篇清晰易懂的Python操控手机APP攻略!

热门文章

  1. scrapy 在迭代爬取时被拒 offsite 增加dont_filter=True
  2. 使 32 位程序使用大于 2GB 的内存
  3. WPF Grid布局
  4. 一个数的约数(个数。约数和)
  5. Java 多线程 简单实例 (Thread)
  6. CentOS 关闭蜂鸣器声音
  7. 构建大型网站架构服务器集群(转)
  8. 网络核心之数据交换-报文、分组交换2
  9. Security+ 学习笔记50 取证技术
  10. [C语言数据存储深度解析]-内存数据搞不懂?三千字长文带你走进数据类型及其存储