springboot @configuration注解的配置, @bean注解方法a, 在@bean注解 getb(){}需要注入a


深度解析@Configuration注解

aop之cglib代理之MethodInterceptor之intercept方法实现之内部调用target实例,而非proxy对象

/**
	 * General purpose AOP callback. Used when the target is dynamic or when the
	 * proxy is not frozen.
	 */
	private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

		private final AdvisedSupport advised;

		public DynamicAdvisedInterceptor(AdvisedSupport advised) {
			this.advised = advised;
		}

		@Override
		@Nullable
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			boolean setProxyContext = false;
			Object target = null;
			TargetSource targetSource = this.advised.getTargetSource();
			try {
				if (this.advised.exposeProxy) {
					// Make invocation available if necessary.
					oldProxy = AopContext.setCurrentProxy(proxy);
					setProxyContext = true;
				}
				// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
				target = targetSource.getTarget();
				Class<?> targetClass = (target != null ? target.getClass() : null);
				// advisor增强
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;
				// Check whether we only have one InvokerInterceptor: that is,
				// no real advice, but just reflective invocation of the target.
				if (chain.isEmpty() && CglibMethodInvocation.isMethodProxyCompatible(method)) {
					// We can skip creating a MethodInvocation: just invoke the target directly.
					// Note that the final invoker must be an InvokerInterceptor, so we know
					// it does nothing but a reflective operation on the target, and no hot
					// swapping or fancy proxying.
					Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
					retVal = invokeMethod(target, method, argsToUse, methodProxy);
				}
				else {
					// We need to create a method invocation... 
					// advisor调用链
					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
				}
				retVal = processReturnType(proxy, target, method, retVal);
				return retVal;
			}
			finally {
				if (target != null && !targetSource.isStatic()) {
					targetSource.releaseTarget(target);
				}
				if (setProxyContext) {
					// Restore old proxy.
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}

		@Override
		public boolean equals(@Nullable Object other) {
			return (this == other ||
					(other instanceof DynamicAdvisedInterceptor &&
							this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));
		}

		/**
		 * CGLIB uses this to drive proxy creation.
		 */
		@Override
		public int hashCode() {
			return this.advised.hashCode();
		}
	}

aop和cglib

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

/**
cglib重写方法
/
    @Bean
    public A a() {
        return new A();
    }


/**
cglib重写方法
/
    @Bean
public B b() {
/**
调用cglib重写的a方法
/
    return new B(a());
}
}

使用 enhancer 对 configClass 进行增强处理,得到增强后的类 enhancedClass。

如果 enhancedClass 与 configClass 不同,意味着类被增强,将用增强后的类替换原有类。

beanDef.setBeanClass(enhancedClass);// 在beanDefinition替换掉class
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
		.....
		// 如果指定属性是full, 则进行下面处理,该属性在前面阶段设置
       if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
				if (!(beanDef instanceof AbstractBeanDefinition)) {
					throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
							beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
				}
				else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
					logger.info("Cannot enhance @Configuration bean definition '" + beanName +
							"' since its singleton instance has been created too early. The typical cause " +
							"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
							"return type: Consider declaring such methods as 'static'.");
				}
                // 加入到增强集合中
				configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
			}
		}
		if (configBeanDefs.isEmpty() || NativeDetector.inNativeImage()) {
			// nothing to enhance -> return immediately
			enhanceConfigClasses.end();
			return;
		}
        // 新建增强器
		ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
		// 遍历待增强的容器列表
        for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
			AbstractBeanDefinition beanDef = entry.getValue();
			// If a @Configuration class gets proxied, always proxy the target class
			beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
			// Set enhanced subclass of the user-specified bean class
			Class<?> configClass = beanDef.getBeanClass();
            // 进行增强处理
			Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
			if (configClass != enhancedClass) {
				if (logger.isTraceEnabled()) {
					logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
							"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
				}
				beanDef.setBeanClass(enhancedClass);
			}
		}
		enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet().size())).end();
	}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/770846.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

实验九 存储过程和触发器

题目 创建并执行一个无参数的存储过程proc_product1&#xff0c;通过该存储过程可以查询商品类别名称为“笔记本电脑”的商品的详细信息&#xff1a;包括商品编号、商品名称、品牌、库存量、单价和上架时间信息 2、创建并执行一个带输入参数的存储过程proc_product2&#xff…

Rethinking Federated Learning with Domain Shift: A Prototype View

CVPR2023,针对分布式数据来自不同的域时,私有模型在其他域上表现出退化性能(具有域转移)的问题。提出用于域转移下联邦学习的联邦原型学习(FPL)。核心思想是构建集群原型和无偏原型,提供富有成效的领域知识和公平的收敛目标。将样本嵌入拉近到属于相同语义的集群原型,而…

【前端】IntersectionObserver 实现图片懒加载和无限滚动

【前端】IntersectionObserver 实现图片懒加载和无限滚动 在前端开发中&#xff0c;性能优化是一个重要的考量因素。随着现代网页和应用的复杂性增加&#xff0c;确保页面快速加载和流畅运行变得越来越重要。本文将介绍一种强大的工具——IntersectionObserver API&#xff0c…

智胜未来:AI如何重塑SaaS用户增长战略

在当今这个数字化时代&#xff0c;SaaS&#xff08;软件即服务&#xff09;已成为企业运营的重要支柱&#xff0c;而人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;正以前所未有的方式重塑着SaaS行业的面貌&#xff0c;特别是对其用户增长战略产生了深远影响。…

每日一题——Python实现PAT乙级1005 继续(3n+1)猜想(举一反三+思想解读+逐步优化)五千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 代码逻辑概述 时间复杂度分析 空间复杂度分析 总结 我要更强 代码优化点…

Openwrt路由器部分ipv6公网地址无法访问的问题

路由器是Openwrt&#xff0c;终端访问ipv6地址经常有些能访问&#xff0c;有些不能访问&#xff0c;一开始以为是运营商问题&#xff0c;后面ssh到openwrt发现所有访问都正常。 查阅资料后才知道是MTU设置问题&#xff0c;Openwrt 默认MTU是1492&#xff0c;使用IPV6应减少60个…

Word文档中公式的常用操作

一、参考资料 二、常用操作 插入公式 Alt 多行公式 Shift Enter 多行公式对齐 WORD Tips: 多行公式编辑及对齐 word自带公式等号对齐&#xff08;可任意符号处对齐&#xff09; 多行公式按照 为基准对齐。 拖动鼠标选中整个公式点击右键&#xff0c;选择【对齐点(…

[激光原理与应用-97]:激光焊接焊中检测系统系列介绍 - 1 - 什么是焊接以及传统的焊接方法

目录 一、什么是焊接 1.1 概述 1.2 基本原理 二、传统的焊接技术与方法 2.1 手工电弧焊&#xff1a; 1、定义与原理 2、特点 3、焊条类型 4、应用领域 5、安全注意事项 2.2 气体保护焊&#xff1a; 1、原理与特点 2、应用领域 3、气体选择 4、注意事项 2.3 电阻…

C++ 文达校内党员管理系统-计算机毕业设计源码20855

目 录 摘要 1 绪论 1.1研究背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2 文达校内党员管理系统系统分析 2.1 可行性分析 2.2 系统功能分析 2.2.1 功能性分析 2.2.2 非功能性分析 2.3 系统用例分析 2.4 系统流程分析 2.4.1 数据流程 2.5.2 业务流程 2.…

CPU/内存/综合性能评估工具汇总-3:unixbench

目录 一、概括二、UnixBench 一、概括 嵌入式开发中对要设计的产品、立项的项目进行设计时&#xff0c;往往需要对关键芯片进行性能评估&#xff0c;本文主要总结基于linux系统的产品在性能评估时的工具使用总结&#xff0c;在aarch64(arm64平台下测试)&#xff0c;板卡根文件…

前端学习(三)CSS介绍及选择符

##最近在忙期末考试&#xff0c;因此前端笔记的梳理并未及时更新。在学习语言过程中&#xff0c;笔记的梳理对于知识的加深very vital.因此坚持在明天学习新知识前将笔记梳理完整。 主要内容&#xff1a;CSS介绍及选择符 最后更新时间&#xff1a;2024/7/4 目录 内容&#x…

Redis 7.x 系列【15】持久化机制之 RDB

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Redis 版本 7.2.5 源码地址&#xff1a;https://gitee.com/pearl-organization/study-redis-demo 文章目录 1. 概述2 执行原理3. 配置项3.1 save3.2 stop-writes-on-bgsave-error3.3 rdbcompress…

HMI 的 UI 风格创造奇迹

HMI 的 UI 风格创造奇迹

关于巴图自动化Profinet协议转Modbus协议网关模块怎么配置IP地址教学

Profinet协议和Modbus协议是工业领域中常用的两种通讯协议&#xff0c;除此以外还有较为常见的&#xff1a;ModbusTCP协议&#xff0c;Profibus协议&#xff0c;Profibus DP协议&#xff0c;EtherCAT协议&#xff0c;EtherNET协议&#xff0c;CAN&#xff0c;CANOPEN等它们在自…

利用运放设计简单有源滤波器(低通、高通、带通)

本文旨在帮助刚接触模电的同学快速设计一个实用可靠的有源滤波器&#xff0c;故我将不会说一些晦涩难懂的原理&#xff0c;只给出仿真电路图。 低通滤波器 图1 低通滤波器 图1所示的是一个截止频率约为1KHz的低通滤波器。 图2 200Hz的情况 图3 2KHz的情况 设计步骤为&#x…

Lesson 47 A cup of coffee

Lesson 47 A cup of coffee 词汇 like v. 喜欢&#xff0c;想要 用法&#xff1a;like 物品 / 人 喜欢……    like 动词ing 喜欢做……&#xff08;习惯性&#xff09;    like to 动词原形 喜欢做……&#xff08;一次性&#xff09; 例句&#xff1a;我喜欢小狗…

一、强化学习基本概念

一、强化学习基本概念 1.1 何为强化学习&#xff1f;1.2 强化学习的环境1.3 强化学习的目标1.4 强化学习的数据 1.1 何为强化学习&#xff1f; 强化学习(Reinforcement Learning, RL)是机器通过与环境交互来实现目标的一种计算方法。机器和环境的一轮交互是指&#xff1a;机器在…

FlinkCDC-3.1.1 DataStream Source

问题&#xff1a; Caused by: java.lang.ClassNotFoundException: org.apache.flink.table.catalog.ObjectPath 解决&#xff1a; 在poml文件中&#xff0c;导入的flink-table依赖把“ <scope>”去掉 <properties><maven.compiler.source>8</maven.compi…

安卓稳定性之crash详解

目录 前言一、Crash 的基本原理二、Crash 分析思路三、实例分析四、预防措施五、参考链接 前言 在开发和测试 Android 应用程序时&#xff0c;遇到应用程序崩溃是很常见的情况。 Android 崩溃指的是应用程序因为异常或错误而无法正常执行&#xff0c;并且导致应用强制关闭。 一…

通过一个单相逆变器仿真深度学习PR控制器

目录 前言 ​编辑 PR控制器的理论 PR控制器不同表达式及其建模 PR控制器连续积分组合及模型 PR控制器连续传递函数及模型 PR控制器离散积分及模型 PR控制器离散传递函数及模型 PR控制器差分方程及模型 系统仿真效果 总结 前言 在项目开发中常用PI控制器&#xff0c;这次在…