当前位置: 首页 > news >正文

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@Nullablepublic 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);}}}@Overridepublic boolean equals(@Nullable Object other) {return (this == other ||(other instanceof DynamicAdvisedInterceptor &&this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));}/*** CGLIB uses this to drive proxy creation.*/@Overridepublic 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重写方法
/@Beanpublic 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 immediatelyenhanceConfigClasses.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 classbeanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);// Set enhanced subclass of the user-specified bean classClass<?> 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();}

相关文章:

  • llm学习-3(向量数据库的使用)
  • 04-《黄蜀葵》
  • 软考的报名详细流程
  • 详解flink sql, calcite logical转flink logical
  • vue 组件el-tree添加结构指示线条
  • Leetcode 538:把二叉搜索树转化为累加树
  • C++ QT 全局信号的实现
  • 【爱上C++】详解string类2:模拟实现、深浅拷贝
  • Java [ 基础 ] HashMap详解 ✨
  • Python中的双向哈希表(双向字典)
  • Qt 使用 QZipReader 解压文件
  • Java中的并行计算与任务分发策略
  • 阿里云智能编程助手的安装使用
  • zoom 会议视频软件的使用
  • MySQL内存使用率高且不释放问题排查与总结
  • 【347天】每日项目总结系列085(2018.01.18)
  • emacs初体验
  • JAVA多线程机制解析-volatilesynchronized
  • Java精华积累:初学者都应该搞懂的问题
  • js算法-归并排序(merge_sort)
  • JS学习笔记——闭包
  • Linux后台研发超实用命令总结
  • nginx 负载服务器优化
  • Protobuf3语言指南
  • Sass Day-01
  • SQL 难点解决:记录的引用
  • Theano - 导数
  • 技术发展面试
  • 精彩代码 vue.js
  • 配置 PM2 实现代码自动发布
  • 首页查询功能的一次实现过程
  • 算法-图和图算法
  • 想使用 MongoDB ,你应该了解这8个方面!
  • 主流的CSS水平和垂直居中技术大全
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • ​520就是要宠粉,你的心头书我买单
  • #传输# #传输数据判断#
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别
  • $.extend({},旧的,新的);合并对象,后面的覆盖前面的
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (3) cmake编译多个cpp文件
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • .Net Core与存储过程(一)
  • .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法
  • .NET 自定义中间件 判断是否存在 AllowAnonymousAttribute 特性 来判断是否需要身份验证
  • .NET/C# 将一个命令行参数字符串转换为命令行参数数组 args
  • .NETCORE 开发登录接口MFA谷歌多因子身份验证
  • .NET大文件上传知识整理
  • .NET多线程执行函数
  • .net开发引用程序集提示没有强名称的解决办法
  • .NET中的Event与Delegates,从Publisher到Subscriber的衔接!
  • .sh 的运行
  • //解决validator验证插件多个name相同只验证第一的问题