spring实例化三:CglibSubclassingInstantiationStrategy

本文深入探讨了Spring框架中CGLIB子类创建策略,详细讲解了SimpleInstantiationStrategy类如何通过CglibSubclassingInstantiationStrategy实现对象实例化,包括CglibSubclassCreator类的作用及其实现细节。

 
     在SimpleInstantiationStrategy类中,留下了包含MethodOverride对象的bd对象定义未做实现,做了抽象。CglibSubclassingInstantiationStrategy类是其中的一种实现方式,采用cglib生成之类方式,实例化对象。
     
下面看SimpleInstantiationStrategy类抽象的两个方法的实现。
@Override
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, String beanName, BeanFactory owner) {
    return instantiateWithMethodInjection(bd, beanName, owner, null);
}
 
@Override
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, String beanName, BeanFactory owner,
        Constructor<?> ctor, Object... args) {
    // 
    return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
}

 

 
可以看出,全部的对象实例化,都集中到类CglibSubclassCreator的方法instantiate中。
 
private static class CglibSubclassCreator {
 
        private static final Class<?>[] CALLBACK_TYPES = new Class<?>[]
                {NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class};
 
        private final RootBeanDefinition beanDefinition;
 
        private final BeanFactory owner;
 
        CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) {
            this.beanDefinition = beanDefinition;
            this.owner = owner;
        }
 
 
        public Object instantiate(Constructor<?> ctor, Object... args) {
            Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
            Object instance;
            // 没传构造方法,直接实例化
            if (ctor == null) {
                instance = BeanUtils.instantiate(subclass);
            }
            else {
                try {
                    // 实例化对象
                    Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
                    instance = enhancedSubclassConstructor.newInstance(args);
                }
                catch (Exception ex) {
                    throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
                            "Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
                }
            }
            Factory factory = (Factory) instance;
            factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
                    new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
                    new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
            return instance;
        }
 
         // cglib生成子类
        private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(beanDefinition.getBeanClass());
            enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
            if (this.owner instanceof ConfigurableBeanFactory) {
                ClassLoader cl = ((ConfigurableBeanFactory) this.owner).getBeanClassLoader();
                enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));
            }
            enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
            enhancer.setCallbackTypes(CALLBACK_TYPES);
            return enhancer.createClass();
        }
    }

 

 
其他都是cglib动态代理的内容,这里不往细走了。 
 

转载于:https://www.cnblogs.com/sten/p/5762519.html

<think>我们正在讨论Spring IOC属性注入的底层实现原理。根据用户的问题和之前的回答,我们需要深入探讨Spring如何实现属性注入,包括注解处理、反射机制、依赖查找和注入过程等。 参考引用: [^1]提到Spring IOC的基本概念和依赖注入方式。 [^2]详细介绍了IOC容器的设计原理和体系结构。 [^3]包含了IOC的底层原理、初始化流程和操作方式(XML和注解)。 [^4]特别指出Spring通过反射机制读取注解(如@Autowired、@Resource)并实现注入,底层使用Field.set()或Method.invoke()。 因此,我们将围绕以下核心点展开: 1. Spring IOC容器如何管理Bean的依赖关系? 2. 注解(如@Autowired)是如何被处理的? 3. 反射在属性注入中的作用。 4. 循环依赖的解决机制(级缓存)。 回答结构: 1. 总体流程概述 2. 关键组件分析(BeanDefinition、BeanPostProcessor等) 3. 注解解析与反射注入的详细步骤 4. 循环依赖处理 5. 相关问题生成 注意:使用中文,并按照要求处理数学公式(虽然本问题可能不涉及数学公式,但若有表达式则按格式处理)。</think>### Spring IOC 属性注入底层实现原理详解 Spring IOC 属性注入的核心是通过**反射机制**和**容器管理**实现依赖关系的自动装配,其底层流程可分为以下关键步骤: --- #### 一、容器初始化阶段 1. **BeanDefinition 加载** Spring 解析配置(XML/注解/JavaConfig)生成 `BeanDefinition` 对象,存储 Bean 的元数据: ```java public interface BeanDefinition { String getBeanClassName(); // Bean 类名 PropertyValues getPropertyValues(); // 需注入的属性 ConstructorArgumentValues getConstructorArgumentValues(); // 构造参数 } ``` - XML 配置通过 `BeanDefinitionParser` 解析 `<property>` 标签[^3] - 注解配置通过 `ClassPathScanningCandidateComponentProvider` 扫描 `@Component` 等注解[^2] 2. **注册 BeanDefinition** 所有 `BeanDefinition` 存入 `BeanDefinitionRegistry`(核心实现类:`DefaultListableBeanFactory`): ```java beanFactory.registerBeanDefinition("userService", userDefinition); ``` --- #### 二、依赖注入执行阶段 当容器实例化 Bean 时,通过以下流程完成属性注入: ##### 1. **实例化对象** - 调用 `InstantiationStrategy`(默认 `CglibSubclassingInstantiationStrategy`) - 通过反射 `Constructor.newInstance()` 创建原始对象 ##### 2. **属性填充(关键步骤)** - **步骤 1:依赖解析** 检查 `BeanDefinition` 中的 `PropertyValues`,确定需注入的属性: ```java for (PropertyValue pv : beanDefinition.getPropertyValues()) { String propertyName = pv.getName(); // 如 "userDao" Object value = pv.getValue(); // 引用类型为 RuntimeBeanReference } ``` - **步骤 2:依赖查找** 对引用类型属性(如 `userDao`),通过 `BeanFactory.getBean()` 从容器获取依赖对象: ```java Object resolvedValue = resolveReference(propertyName, (RuntimeBeanReference) value); ``` - **步骤 3:反射注入** 使用反射 API 将值注入目标属性: ```java Field field = targetClass.getDeclaredField("userDao"); field.setAccessible(true); field.set(beanInstance, resolvedValue); // 关键注入操作 ``` 或通过 Setter 方法注入: ```java Method setter = targetClass.getMethod("setUserDao", UserDao.class); setter.invoke(beanInstance, resolvedValue); ``` ##### 3. **注解处理(@Autowired/@Resource)** - **`AutowiredAnnotationBeanPostProcessor`** 扫描 `@Autowired` 注解字段/方法 - 通过 `InjectionMetadata` 收集所有需注入的元素: ```java List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); elements.add(new AutowiredFieldElement(field, required)); ``` - 最终调用 `Field.set()` 或 `Method.invoke()` 完成注入[^4] --- #### 、循环依赖解决方案(级缓存) 当发生属性注入的循环依赖(如 A → B → A),Spring 通过级缓存解决: ```java // DefaultSingletonBeanRegistry 中的级缓存 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(); // 一级缓存(完整Bean) private final Map<String, Object> earlySingletonObjects = new HashMap<>(); // 二级缓存(早期引用) private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(); // 级缓存(对象工厂) ``` **解决流程**: 1. 创建 A 实例后,将原始对象包装为 `ObjectFactory` 放入级缓存 2. 为 A 注入属性时发现依赖 B,触发 B 的创建 3. 为 B 注入属性时从级缓存获取 A 的早期引用(未完全初始化的 A) 4. B 完成初始化后,A 继续注入完整的 B 实例[^2] > ⚠️ **限制**:仅支持单例模式下的Setter/字段注入,构造器注入的循环依赖会抛出 `BeanCurrentlyInCreationException` --- #### 四、扩展机制支撑 Spring 通过扩展点增强注入能力: 1. **`BeanPostProcessor`** 在注入前后插入自定义逻辑(如 `@Autowired` 由 `AutowiredAnnotationBeanPostProcessor` 实现) 2. **`BeanFactoryPostProcessor`** 修改 `BeanDefinition`(如 `PropertySourcesPlaceholderConfigurer` 解析 `${}` 占位符) 3. **`InstantiationAwareBeanPostProcessor`** 控制实例化过程(如 AOP 代理对象的生成) --- ### 原理总结 | 关键机制 | 实现组件 | 作用 | |------------------|-----------------------------------|--------------------------------------| | 元数据管理 | `BeanDefinition` | 存储 Bean 的依赖关系 | | 依赖解析 | `DependencyDescriptor` | 描述注入点(字段/方法参数) | | 反射注入 | `Field.set()`/`Method.invoke()` | 实际注入操作 | | 注解处理 | `AutowiredAnnotationBeanPostProcessor` | 解析 `@Autowired`/`@Value` | | 循环依赖解决 | 级缓存机制 | 打破单例 Bean 循环依赖 | > 整个流程体现了 **控制反转** 的核心思想:开发者定义依赖关系,容器负责装配实现[^1]。 --- ### 相关问题 1. Spring 如何解决构造器注入的循环依赖问题? 2. `@Autowired` 和 `@Resource` 注解在注入流程中有何本质区别? 3. 如何通过自定义 `BeanPostProcessor` 实现加密属性的自动解密? 4. 为什么字段注入(`@Autowired`)比 Setter 注入更容易导致循环依赖问题? [^1]: Spring IOC详解:从原理到实战 [^2]: Spring IOC体系结构设计原理详解 [^3]: Spring IOC详解 - IOC操作Bean管理(XML方式) [^4]: spring ioc实现原理 - 反射机制实现依赖注入
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值