spring aop原理_源码解析Spring的AOP原理(一)
做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原理(一)相关推荐
- 【Spring Boot实战】源码解析Spring Boot自动配置原理
一.简介 Spring致力于让Java开发更简单,SpringBoot致力于让使用Spring进行Java开发更简单,SpringCloud致力于基于SpringBoot构建微服务生态圈,让微服务开发 ...
- 【特征匹配】ORB原理与源码解析
相关 : Fast原理与源码解析 Brief描述子原理与源码解析 Harris原理与源码解析 http://blog.csdn.net/luoshixian099/article/details/48 ...
- PCA-SIFT原理及源码解析
相关: SIFT原理与源码解析 SURF原理与源码解析 ORB原理与源码解析 FAST原理与源码解析 BRIEF描述子原理与源码解析 Harris原理与源码解析 转载请注明出处:http://blog ...
- Spring Boot 核心原理与源码解析 - 目录
准备重新写 SpringBoot 配置文件解析原理 , 先在这里把要写的内容记下来 Spring Boot 核心原理与源码解析 - 目录 1\何时解析\如何解析 application.propert ...
- Spring源码深度解析(郝佳)-学习-源码解析-Spring MVC(三)-Controller 解析
在之前的博客中Spring源码深度解析(郝佳)-学习-源码解析-Spring MVC(一),己经对 Spring MVC 的框架做了详细的分析,但是有一个问题,发现举的例子不常用,因为我们在实际开发项 ...
- spring 注解试事物源码解析
spring 注解试事物源码解析 基于xml注解式事务入口 public class TxNamespaceHandler extends NamespaceHandlerSupport {stati ...
- Spring事件机制Event源码解析(未完待续)
Spring事件机制Event源码解析(未完待续) 监听器: ApplicationEvent事件 ApplicationListener监听器(观察者) ApplicationEventMultic ...
- SpringMVC工作原理及源码解析
SpringMVC工作原理及源码解析 一:SpringMVC原理图 二:SpringMVC的主要组件 1.前端控制器DispatcherServlet: 2.处理器映射器HandlerMapping: ...
- Redis进阶- Redisson分布式锁实现原理及源码解析
文章目录 Pre 用法 Redisson分布式锁实现原理 Redisson分布式锁源码分析 redisson.getLock(lockKey) 的逻辑 redissonLock.lock()的逻辑 r ...
- php 框架源码分析,Laravel框架源码解析之模型Model原理与用法解析
本文实例讲述了Laravel框架源码解析之模型Model原理与用法.分享给大家供大家参考,具体如下: 前言 提前预祝猿人们国庆快乐,吃好.喝好.玩好,我会在电视上看着你们. 根据单一责任开发原则来讲, ...
最新文章
- vue 手写一个时间选择器
- c语言字符串的一个简单例子,把一个字符串中的小写字母改成大写字母
- [XSS神器]XssEncode chrome插件 - 0x_Jin
- 准备重新回归信息安全产业
- 080520 雨 大风
- 有道词典使用离线翻译
- 《数据结构复习》扩展线性链表的广义表
- openlayers示例教程002:简析EPSG:4326 和 EPSG: 3857
- ORACLE 中利用推理逻辑去算 上年同期 ,注意:ORACLE中查询条件是带有推理逻辑功能的,及oracle中的推理逻辑
- 大数据时代下的网络安全与数据隐私论文
- 【错误记录】Google Play 上架报错 ( 此版本不符合 Google Play 关于提供 64 位版本应用的要求。| 如果提供 x86 架构动态库则必须提供 x86_64 架构的动态库 )
- [深度学习论文笔记]UCTransNet:从transformer的通道角度重新思考U-Net中的跳跃连接
- U盘出现物理故障都有哪些表现
- 万字详解什么是生成对抗网络GAN
- 2019年第八届java B组蓝桥杯省赛真题
- 外网如何访问内网/局域网网站【内网穿透】
- FPGA——SPI总线控制flash(1)(含代码)
- 农业虫害识别相关论文——调研整理
- leetcode 1646
- python教程app攻略_一篇清晰易懂的Python操控手机APP攻略!