【死磕 Spring】----- IOC 之 属性填充

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介:
doCreateBean() 主要用于完成 bean 的创建和初始化工作,我们可以将其分为四个过程:

createBeanInstance() 实例化 bean

populateBean() 属性填充

循环依赖的处理

initializeBean() 初始化 bean

第一个过程实例化 bean 已经在前面两篇博客分析完毕了,这篇博客开始分析 属性填充,也就是 populateBean(),该函数的作用是将 BeanDefinition 中的属性值赋值给 BeanWrapper 实例对象(对于 BeanWrapper 我们后续专门写文分析)。

 
  1. protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {

  2. // 没有实例化对象

  3. if (bw == null) {

  4. // 有属性抛出异常

  5. if (mbd.hasPropertyValues()) {

  6. throw new BeanCreationException(

  7. mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");

  8. }

  9. else {

  10. // 没有属性直接返回

  11. return;

  12. }

  13. }


  14. // 在设置属性之前给 InstantiationAwareBeanPostProcessors 最后一次改变 bean 的机会

  15. boolean continueWithPropertyPopulation = true;


  16. // bena 不是"合成"的,即未由应用程序本身定义

  17. // 是否持有 InstantiationAwareBeanPostProcessor

  18. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {

  19. // 迭代所有的 BeanPostProcessors

  20. for (BeanPostProcessor bp : getBeanPostProcessors()) {

  21. // 如果为 InstantiationAwareBeanPostProcessor

  22. if (bp instanceof InstantiationAwareBeanPostProcessor) {

  23. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

  24. // 返回值为是否继续填充 bean

  25. // postProcessAfterInstantiation:如果应该在 bean上面设置属性则返回true,否则返回false

  26. // 一般情况下,应该是返回true,返回 false 的话,

  27. // 将会阻止在此 Bean 实例上调用任何后续的 InstantiationAwareBeanPostProcessor 实例。

  28. if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {

  29. continueWithPropertyPopulation = false;

  30. break;

  31. }

  32. }

  33. }

  34. }


  35. // 如果后续处理器发出停止填充命令,则终止后续操作

  36. if (!continueWithPropertyPopulation) {

  37. return;

  38. }


  39. // bean 的属性值

  40. PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);


  41. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||

  42. mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {


  43. // 将 PropertyValues 封装成 MutablePropertyValues 对象

  44. // MutablePropertyValues 允许对属性进行简单的操作,

  45. // 并提供构造函数以支持Map的深度复制和构造。

  46. MutablePropertyValues newPvs = new MutablePropertyValues(pvs);


  47. // 根据名称自动注入

  48. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {

  49. autowireByName(beanName, mbd, bw, newPvs);

  50. }


  51. // 根据类型自动注入

  52. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {

  53. autowireByType(beanName, mbd, bw, newPvs);

  54. }


  55. pvs = newPvs;

  56. }


  57. // 是否已经注册了 InstantiationAwareBeanPostProcessors

  58. boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();

  59. // 是否需要进行依赖检查

  60. boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);


  61. if (hasInstAwareBpps || needsDepCheck) {

  62. if (pvs == null) {

  63. pvs = mbd.getPropertyValues();

  64. }


  65. // 从 bw 对象中提取 PropertyDescriptor 结果集

  66. // PropertyDescriptor:可以通过一对存取方法提取一个属性

  67. PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);

  68. if (hasInstAwareBpps) {

  69. for (BeanPostProcessor bp : getBeanPostProcessors()) {

  70. if (bp instanceof InstantiationAwareBeanPostProcessor) {

  71. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

  72. // 对所有需要依赖检查的属性进行后处理

  73. pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);

  74. if (pvs == null) {

  75. return;

  76. }

  77. }

  78. }

  79. }

  80. if (needsDepCheck) {

  81. // 依赖检查,对应 depends-on 属性

  82. checkDependencies(beanName, mbd, filteredPds, pvs);

  83. }

  84. }


  85. if (pvs != null) {

  86. // 将属性应用到 bean 中

  87. applyPropertyValues(beanName, mbd, bw, pvs);

  88. }

  89. }

处理流程如下:

根据 hasInstantiationAwareBeanPostProcessors 属性来判断是否需要在注入属性之前给 InstantiationAwareBeanPostProcessors 最后一次改变 bean 的机会,此过程可以控制 Spring 是否继续进行属性填充。

根据注入类型的不同来判断是根据名称来自动注入( autowireByName())还是根据类型来自动注入( autowireByType()),统一存入到 PropertyValues 中,PropertyValues 用于描述 bean 的属性。

判断是否需要进行 BeanPostProcessor 和 依赖检测。

将所有 PropertyValues 中的属性填充到 BeanWrapper 中。

自动注入

Spring 会根据注入类型( byName / byType )的不同,调用不同的方法( autowireByName() / autowireByType())来注入属性值。

autowireByName()

方法 autowireByName() 是根据属性名称完成自动依赖注入的,代码如下:

 
  1. protected void autowireByName(

  2. String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {


  3. // 对 Bean 对象中非简单属性

  4. String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);

  5. for (String propertyName : propertyNames) {

  6. // 如果容器中包含指定名称的 bean,则将该 bean 注入到 bean中

  7. if (containsBean(propertyName)) {

  8. // 递归初始化相关 bean

  9. Object bean = getBean(propertyName);

  10. // 为指定名称的属性赋予属性值

  11. pvs.add(propertyName, bean);

  12. // 属性依赖注入

  13. registerDependentBean(propertyName, beanName);

  14. if (logger.isDebugEnabled()) {

  15. logger.debug("Added autowiring by name from bean name '" + beanName +

  16. "' via property '" + propertyName + "' to bean named '" + propertyName + "'");

  17. }

  18. }

  19. else {

  20. if (logger.isTraceEnabled()) {

  21. logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +

  22. "' by name: no matching bean found");

  23. }

  24. }

  25. }

  26. }

该方法逻辑很简单,获取该 bean 的非简单属性,什么叫做非简单属性呢?就是类型为对象类型的属性,但是这里并不是将所有的对象类型都都会找到,比如 8 个原始类型,String 类型 ,Number类型、Date类型、URL类型、URI类型等都会被忽略,如下:

 
  1. protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {

  2. Set<String> result = new TreeSet<>();

  3. PropertyValues pvs = mbd.getPropertyValues();

  4. PropertyDescriptor[] pds = bw.getPropertyDescriptors();

  5. for (PropertyDescriptor pd : pds) {

  6. if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&

  7. !BeanUtils.isSimpleProperty(pd.getPropertyType())) {

  8. result.add(pd.getName());

  9. }

  10. }

  11. return StringUtils.toStringArray(result);

  12. }

过滤条件为:有可写方法、依赖检测中没有被忽略、不是简单属性类型。其实这里获取的就是需要依赖注入的属性。

获取需要依赖注入的属性后,通过迭代、递归的方式初始化相关的 bean,然后调用 registerDependentBean()完成注册依赖,如下:

 
  1. public void registerDependentBean(String beanName, String dependentBeanName) {

  2. String canonicalName = canonicalName(beanName);


  3. synchronized (this.dependentBeanMap) {

  4. Set<String> dependentBeans =

  5. this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));

  6. if (!dependentBeans.add(dependentBeanName)) {

  7. return;

  8. }

  9. }


  10. synchronized (this.dependenciesForBeanMap) {

  11. Set<String> dependenciesForBean =

  12. this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));

  13. dependenciesForBean.add(canonicalName);

  14. }

  15. }

autowireByType()

 
  1. protected void autowireByType(

  2. String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {


  3. // 获取 TypeConverter 实例

  4. // 使用自定义的 TypeConverter,用于取代默认的 PropertyEditor 机制

  5. TypeConverter converter = getCustomTypeConverter();

  6. if (converter == null) {

  7. converter = bw;

  8. }


  9. Set<String> autowiredBeanNames = new LinkedHashSet<>(4);

  10. // 获取非简单属性

  11. String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);


  12. for (String propertyName : propertyNames) {

  13. try {

  14. // 获取 PropertyDescriptor 实例

  15. PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);


  16. // 不要尝试按类型

  17. if (Object.class != pd.getPropertyType()) {

  18. // 探测指定属性的 set 方法

  19. MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);


  20. boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());

  21. DependencyDescriptor desc = new AbstractAutowireCapableBeanFactory.AutowireByTypeDependencyDescriptor(methodParam, eager);


  22. // 解析指定 beanName 的属性所匹配的值,并把解析到的属性名称存储在 autowiredBeanNames 中

  23. // 当属性存在过个封装 bean 时将会找到所有匹配的 bean 并将其注入

  24. Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);


  25. if (autowiredArgument != null) {

  26. pvs.add(propertyName, autowiredArgument);

  27. }


  28. // 迭代方式注入 bean

  29. for (String autowiredBeanName : autowibeanredBeanNames) {

  30. registerDependentBean(autowiredBeanName, beanName);

  31. if (logger.isDebugEnabled()) {

  32. logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +

  33. propertyName + "' to bean named '" + autowiredBeanName + "'");

  34. }

  35. }

  36. autowiredBeanNames.clear();

  37. }

  38. }

  39. catch (BeansException ex) {

  40. throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);

  41. }

  42. }

  43. }

其实主要过程和根据名称自动注入差不多都是找到需要依赖注入的属性,然后通过迭代的方式寻找所匹配的 bean,最后调用 registerDependentBean() 注册依赖。不过相对于 autowireByName() 而言,根据类型寻找相匹配的 bean 过程比较复杂,下面我们就分析这个复杂的过程,如下:

 
  1. public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,

  2. @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {


  3. // 初始化参数名称发现器,该方法并不会在这个时候尝试检索参数名称

  4. // getParameterNameDiscoverer 返回 parameterNameDiscoverer 实例,parameterNameDiscoverer 方法参数名称的解析器

  5. descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());


  6. // 依赖类型为 Optional 类型

  7. if (Optional.class == descriptor.getDependencyType()) {

  8. // 创建 Optional 实例依赖类型

  9. return createOptionalDependency(descriptor, requestingBeanName);

  10. }


  11. // 依赖类型为ObjectFactory、ObjectProvider

  12. else if (ObjectFactory.class == descriptor.getDependencyType() ||

  13. ObjectProvider.class == descriptor.getDependencyType()) {

  14. // ObjectFactory / ObjectProvider 用于 用于延迟解析依赖项

  15. return new DefaultListableBeanFactory.DependencyObjectProvider(descriptor, requestingBeanName);

  16. }


  17. else if (javaxInjectProviderClass == descriptor.getDependencyType()) {

  18. // javaxInjectProviderClass 类注入的特殊处理

  19. return new DefaultListableBeanFactory.Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);

  20. }

  21. else {

  22. // 为实际依赖关系目标的延迟解析构建代理

  23. // 默认实现返回 null

  24. Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(

  25. descriptor, requestingBeanName);

  26. if (result == null) {

  27. // 通用处理逻辑

  28. result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);

  29. }

  30. return result;

  31. }

  32. }

这里我们关注通用处理逻辑: doResolveDependency(),如下:

 
  1. public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,

  2. @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {


  3. // 注入点

  4. InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);

  5. try {

  6. // 针对给定的工厂给定一个快捷实现的方式,例如考虑一些预先解析的信息

  7. // 在进入所有bean的常规类型匹配算法之前,解析算法将首先尝试通过此方法解析快捷方式。

  8. // 子类可以覆盖此方法

  9. Object shortcut = descriptor.resolveShortcut(this);

  10. if (shortcut != null) {

  11. // 返回快捷的解析信息

  12. return shortcut;

  13. }


  14. // 依赖的类型

  15. Class<?> type = descriptor.getDependencyType();

  16. // 支持 Spring 的注解 @value

  17. Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);

  18. if (value != null) {

  19. if (value instanceof String) {

  20. String strVal = resolveEmbeddedValue((String) value);

  21. BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);

  22. value = evaluateBeanDefinitionString(strVal, bd);

  23. }

  24. TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());

  25. return (descriptor.getField() != null ?

  26. converter.convertIfNecessary(value, type, descriptor.getField()) :

  27. converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));

  28. }


  29. // 解析复合 bean,其实就是对 bean 的属性进行解析

  30. // 包括:数组、Collection 、Map 类型

  31. Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);

  32. if (multipleBeans != null) {

  33. return multipleBeans;

  34. }


  35. // 查找与类型相匹配的 bean

  36. // 返回值构成为:key = 匹配的 beanName,value = beanName 对应的实例化 bean

  37. Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);

  38. // 没有找到,检验 @autowire 的 require 是否为 true

  39. if (matchingBeans.isEmpty()) {

  40. // 如果 @autowire 的 require 属性为 true ,但是没有找到相应的匹配项,则抛出异常

  41. if (isRequired(descriptor)) {

  42. raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);

  43. }

  44. return null;

  45. }


  46. String autowiredBeanName;

  47. Object instanceCandidate;


  48. if (matchingBeans.size() > 1) {

  49. // 确认给定 bean autowire 的候选者

  50. // 按照 @Primary 和 @Priority 的顺序

  51. autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);

  52. if (autowiredBeanName == null) {

  53. if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {

  54. // 唯一性处理

  55. return descriptor.resolveNotUnique(type, matchingBeans);

  56. } else {

  57. // 在可选的Collection / Map的情况下,默默地忽略一个非唯一的情况:可能它是一个多个常规bean的空集合

  58. return null;

  59. }

  60. }

  61. instanceCandidate = matchingBeans.get(autowiredBeanName);

  62. } else {

  63. // We have exactly one match.

  64. Map.Entry<Staring, Object> entry = matchingBeans.entrySet().iterator().next();

  65. autowiredBeanName = entry.getKey();

  66. instanceCandidate = entry.getValue();

  67. }


  68. if (autowiredBeanNames != null) {

  69. autowiredBeanNames.add(autowiredBeanName);

  70. }

  71. if (instanceCandidate instanceof Class) {

  72. instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);

  73. }

  74. Object result = instanceCandidate;

  75. if (result instanceof NullBean) {

  76. if (isRequired(descriptor)) {

  77. raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);

  78. }

  79. result = null;

  80. }

  81. if (!ClassUtils.isAssignableValue(type, result)) {

  82. throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());

  83. }

  84. return result;

  85. } finally {

  86. ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);

  87. }

  88. }

到这里就已经完成了所有属性的注入了。 populateBean() 该方法就已经完成了一大半工作了,下一步则是对依赖 bean 的检测和 PostProcessor 处理,这个我们后面分析,下面分析该方法的最后一步: applyPropertyValues()

applyPropertyValues

其实上面只是完成了所有注入属性的获取,将获取的属性封装在 PropertyValues 的实例对象 pvs 中,并没有应用到已经实例化的 bean 中,而 applyPropertyValues() 则是完成这一步骤的。

 
  1. protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {

  2. if (pvs.isEmpty()) {

  3. return;

  4. }


  5. if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {

  6. ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());

  7. }


  8. // MutablePropertyValues 类型属性

  9. MutablePropertyValues mpvs = null;

  10. // 原始类型

  11. List<PropertyValue> original;



  12. if (pvs instanceof MutablePropertyValues) {

  13. mpvs = (MutablePropertyValues) pvs;

  14. if (mpvs.isConverted()) {

  15. try {

  16. // 设置到 BeanWrapper 中去

  17. bw.setPropertyValues(mpvs);

  18. return;

  19. }

  20. catch (BeansException ex) {

  21. throw new BeanCreationException(

  22. mbd.getResourceDescription(), beanName, "Error setting property values", ex);

  23. }

  24. }

  25. original = mpvs.getPropertyValueList();

  26. }

  27. else {

  28. // 如果 pvs 不是 MutablePropertyValues 类型,则直接使用原始类型

  29. original = Arrays.asList(pvs.getPropertyValues());

  30. }


  31. // 获取 TypeConverter

  32. TypeConverter converter = getCustomTypeConverter();

  33. if (converter == null) {

  34. converter = bw;

  35. }


  36. // 获取对应的解析器

  37. BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);


  38. // Create a deep copy, resolving any references for values.

  39. List<PropertyValue> deepCopy = new ArrayList<>(original.size());

  40. boolean resolveNecessary = false;

  41. // 遍历属性,将属性转换为对应类的对应属性的类型

  42. for (PropertyValue pv : original) {

  43. if (pv.isConverted()) {

  44. deepCopy.add(pv);

  45. }

  46. else {

  47. String propertyName = pv.getName();

  48. Object originalValue = pv.getValue();

  49. Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);

  50. Object convertedValue = resolvedValue;

  51. boolean convertible = bw.isWritableProperty(propertyName) &&

  52. !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);

  53. if (convertible) {

  54. convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);

  55. }

  56. // Possibly store converted value in merged bean definition,

  57. // in order to avoid re-conversion for every created bean instance.

  58. if (resolvedValue == originalValue) {

  59. if (convertible) {

  60. pv.setConvertedValue(convertedValue);

  61. }

  62. deepCopy.add(pv);

  63. }

  64. else if (convertible && originalValue instanceof TypedStringValue &&

  65. !((TypedStringValue) originalValue).isDynamic() &&

  66. !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {

  67. pv.setConvertedValue(convertedValue);

  68. deepCopy.add(pv);

  69. }

  70. else {

  71. resolveNecessary = true;

  72. deepCopy.add(new PropertyValue(pv, convertedValue));

  73. }

  74. }

  75. }

  76. if (mpvs != null && !resolveNecessary) {

  77. mpvs.setConverted();

  78. }


  79. // Set our (possibly massaged) deep copy.

  80. try {

  81. bw.setPropertyValues(new MutablePropertyValues(deepCopy));

  82. }

  83. catch (BeansException ex) {

  84. throw new BeanCreationException(

  85. mbd.getResourceDescription(), beanName, "Error setting property values", ex);

  86. }

  87. }

至此, doCreateBean() 第二个过程:属性填充 已经分析完成了,下篇分析第三个过程:循环依赖的处理,其实循环依赖并不仅仅只是在 doCreateBean() 中处理,其实在整个加载 bean 的过程中都有涉及,所以下篇内容并不仅仅只局限于 doCreateBean()


原文发布时间为: 2018-11-05
本文作者Java技术驿站
本文来自云栖社区合作伙伴“Java技术驿站”,了解相关信息可以关注“Java技术驿站”。

相关文章
|
21天前
|
XML 缓存 Java
搞透 IOC、Spring IOC ,看这篇就够了!
本文详细解析了Spring框架的核心内容——IOC(控制反转)及其依赖注入(DI)的实现原理,帮助读者理解如何通过IOC实现组件解耦,提高程序的灵活性和可维护性。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
|
13天前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
27 0
|
1月前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
127 9
|
1月前
|
存储 开发框架 Java
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
文章详细介绍了Spring、IOC、DI的概念和关系,解释了控制反转(IOC)和依赖注入(DI)的原理,并提供了IOC的代码示例,阐述了Spring框架作为IOC容器的应用。
31 0
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
|
2月前
|
缓存 Java Spring
手写Spring Ioc 循环依赖底层源码剖析
在Spring框架中,IoC(控制反转)是一个核心特性,它通过依赖注入(DI)实现了对象间的解耦。然而,在实际开发中,循环依赖是一个常见的问题。
40 4
|
1月前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
66 0
|
1月前
|
XML Java 数据格式
Spring的IOC和AOP
Spring的IOC和AOP
46 0
|
3月前
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
|
5月前
|
XML Java 数据格式
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
47 1
|
2月前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
216 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)