Spring Bean的创建过程及相关扩展点(下)

简介: Spring Bean的创建过程及相关扩展点

创建Bean实例

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {
    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    // 如果是单例
    if (mbd.isSingleton()) {
      // 清除缓存
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
      // 创建Bean实例,这个instanceWrapper是已经被包装的对象了
      // 多种创建Bean的方法,了解后可以更灵活地创建Bean对象
      // *****这是重点***********这是重点***********这是重点******
      instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
      mbd.resolvedTargetType = beanType;
    }
    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
        try {
          // 扩展点
          // 解析@Autowired,@Value,@Inject注解,把对应的字段和方法解析好设置进BeanDefinition
          // 入口在AutowiredAnnotationBeanPostProcessor类中,可查看构造函数
          // *****这是重点***********这是重点***********这是重点******
          applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
        }
        catch (Throwable ex) {
          throw new BeanCreationException(mbd.getResourceDescription(), beanName,
              "Post-processing of merged bean definition failed", ex);
        }
        mbd.postProcessed = true;
      }
    }
    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    // 如果这个Bean定义是单例,并且允许循环依赖,并且正在创建当中,那么就允许提前暴露
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
        isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
      if (logger.isTraceEnabled()) {
        logger.trace("Eagerly caching bean '" + beanName +
            "' to allow for resolving potential circular references");
      }
      // AOP入口,方便增强Bean。此时的Bean还没有设置属性,正好可以在其他Bean依赖它的时候通过getBean方法从第三级缓存中取出来;在这个过程中可以对Bean进行增强。
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }
    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
      // 设置属性值,通过属性名和字段类型,从IOC容器中getBean取值
      populateBean(beanName, mbd, instanceWrapper);
      // 调用初始化方法;先处理Aware结尾的接口,比如BeanNameAware,BeanClassLoaderAware,BeanFactoryAware接口;
      // 先调用postProcessBeforeInitialization
      // 执行初始化方法;InitializingBean接口的afterPropertiesSet方法;还有自定义的初始化方法,比如@PostConstruct注解的方法,init-method配置的方法名
      // 再调用postProcessAfterInitialization
      exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {
      if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
        throw (BeanCreationException) ex;
      }
      else {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
      }
    }
    if (earlySingletonExposure) {
      Object earlySingletonReference = getSingleton(beanName, false);
      if (earlySingletonReference != null) {
        if (exposedObject == bean) {
          exposedObject = earlySingletonReference;
        }
        else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
          String[] dependentBeans = getDependentBeans(beanName);
          Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
          for (String dependentBean : dependentBeans) {
            if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
              actualDependentBeans.add(dependentBean);
            }
          }
          if (!actualDependentBeans.isEmpty()) {
            throw new BeanCurrentlyInCreationException(beanName,
                "Bean with name '" + beanName + "' has been injected into other beans [" +
                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                "] in its raw version as part of a circular reference, but has eventually been " +
                "wrapped. This means that said other beans do not use the final version of the " +
                "bean. This is often the result of over-eager type matching - consider using " +
                "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
          }
        }
      }
    }
    // Register bean as disposable.
    try {
      // 注册销毁方法;比如@PreDestroy注解的方法,或者实现了DisposableBean接口的实现,还有就是配置的destroy-method方法
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(
          mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }
    // 返回Bean实例
    return exposedObject;
  }
复制代码

创建Bean实例createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // Make sure bean class is actually resolved at this point.
    // 通过BeanDefinition和beanName获取Class
    Class<?> beanClass = resolveBeanClass(mbd, beanName);
    // 如果这个类的修饰符不是pubic,那么直接抛异常
    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
          "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    }
    // 检查有没有指定的创造Bean实例的方法
    // beanDefinition.setInstanceSupplier(SupplierBean::createUser);
    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    if (instanceSupplier != null) {
      return obtainFromSupplier(instanceSupplier, beanName);
    }
    // 检查是否有工厂方法。包括静态工厂、实例工厂、@Bean这种方式也会被转换成工厂方法
    if (mbd.getFactoryMethodName() != null) {
      return instantiateUsingFactoryMethod(beanName, mbd, args);
    }
    // Shortcut when re-creating the same bean...
    // 构造器实例化
    // 快速实例化对象,所谓的快速实例化对象,其实就是使用了缓存
    boolean resolved = false;
    boolean autowireNecessary = false;
    // 外部化参数,只能当无外部参数时才使用缓存。不推荐使用外部化参数
    if (args == null) {
      synchronized (mbd.constructorArgumentLock) {
        if (mbd.resolvedConstructorOrFactoryMethod != null) {
          // 是否使用缓存,其中autowireNecessary表示是否使用有参构造器
          resolved = true;
          autowireNecessary = mbd.constructorArgumentsResolved;
        }
      }
    }
    // 使用缓存,其中autowireNecessary表示是否使用有参构造器
    if (resolved) {
      if (autowireNecessary) {
        // 这个情况就是使用了已经解析好的BeanDefinition,直接从BeanDefinition中获取构造函数和参数
        // 比如Property模式的时候,就会调用这个逻辑创建Bean
        return autowireConstructor(beanName, mbd, null, null);
      }
      else {
        // 反射创建对象实例
        return instantiateBean(beanName, mbd);
      }
    }
    // Candidate constructors for autowiring?
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
        mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
      // @Autowire注解的构造函数,多个构造函数
      return autowireConstructor(beanName, mbd, ctors, args);
    }
    // Preferred constructors for default construction?
    ctors = mbd.getPreferredConstructors();
    if (ctors != null) {
      // @Autowire注解的构造函数,默认的构造函数
      return autowireConstructor(beanName, mbd, ctors, null);
    }
    // No special handling: simply use no-arg constructor.
    // 反射创建对象实例
    return instantiateBean(beanName, mbd);
  }
复制代码

总结一下就是:

1.先看看有没有指定的工厂方法创建对象;比如Supplier,factory-method

2.其次匹配构造函数;这都是自定匹配的

3.最终就是反射无参构造函数创建对象

// 这个扩展点其实是用来增强BeanDefinition。比如AutowiredAnnotationBeanPostProcessor就是用来解析@Autowired注解的,方便后面给对象属性赋值
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
   for (BeanPostProcessor bp : getBeanPostProcessors()) {
      if (bp instanceof MergedBeanDefinitionPostProcessor) {
        // MergedBeanDefinitionPostProcessor子类可实现BeanDefinition的扩展
         MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
         bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
      }
   }
}
复制代码

设置Bean对象属性值

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    if (bw == null) {
      if (mbd.hasPropertyValues()) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
      }
      else {
        // Skip property population phase for null instance.
        return;
      }
    }
    // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
    // state of the bean before properties are set. This can be used, for example,
    // to support styles of field injection.
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
          // ********扩展点**********扩展点**********扩展点**********扩展点**
          // 一看这就是扩展点,一旦postProcessAfterInstantiation返回false,那么直接就跳出不会继续执行设置相关属性值了
          InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
          if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
            return;
          }
        }
      }
    }
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
      MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
      // Add property values based on autowire by name if applicable.
      if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
        // 根据name查找属性值,其实里面也是通过getBean()获取属性值
        autowireByName(beanName, mbd, bw, newPvs);
      }
      // Add property values based on autowire by type if applicable.
      if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
        // 根据类型查找,其实里面也是通过getBean()获取属性值
        autowireByType(beanName, mbd, bw, newPvs);
      }
      pvs = newPvs;
    }
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
    PropertyDescriptor[] filteredPds = null;
    if (hasInstAwareBpps) {
      if (pvs == null) {
        pvs = mbd.getPropertyValues();
      }
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
          // ******又是扩展点******又是扩展点******又是扩展点******又是扩展点****
          // 通过postProcessProperties可以拦截具体的属性并赋值
          InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
          PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
          if (pvsToUse == null) {
            if (filteredPds == null) {
              filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            }
            // ******又是扩展点******又是扩展点******又是扩展点******又是扩展点****
            // 如果没有在postProcessProperties进行扩展,可以在postProcessPropertyValues上扩展
            pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
              return;
            }
          }
          pvs = pvsToUse;
        }
      }
    }
    if (needsDepCheck) {
      if (filteredPds == null) {
        filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
      }
      checkDependencies(beanName, mbd, filteredPds, pvs);
    }
    if (pvs != null) {
      // 赋值,不用管
      applyPropertyValues(beanName, mbd, bw, pvs);
    }
  }
复制代码

初始化Bean实例:

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
        invokeAwareMethods(beanName, bean);
        return null;
      }, getAccessControlContext());
    }
    else {
      // 调用Aware相关接口;扩展点,可以用开获取Bean名称、类加载器、容器实例
      invokeAwareMethods(beanName, bean);
    }
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
      // 前置处理;扩展点,可以用来织入功能实现AOP
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    try {
      // 初始化;用来调用InitializingBean接口、@PostConstruct注解方法、init-method方法
      invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
      throw new BeanCreationException(
          (mbd != null ? mbd.getResourceDescription() : null),
          beanName, "Invocation of init method failed", ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
      // 后置处理;扩展点,可以用来织入功能实现AOP
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
  }
// 处理BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口
private void invokeAwareMethods(String beanName, Object bean) {
    if (bean instanceof Aware) {
      if (bean instanceof BeanNameAware) {
        ((BeanNameAware) bean).setBeanName(beanName);
      }
      if (bean instanceof BeanClassLoaderAware) {
        ClassLoader bcl = getBeanClassLoader();
        if (bcl != null) {
          ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
        }
      }
      if (bean instanceof BeanFactoryAware) {
        ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
      }
    }
  }
@Override
  public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
      throws BeansException {
    Object result = existingBean;
    // AOP入口
    // *****扩展点*********扩展点*********扩展点*********扩展点*********扩展点****
    // 实现BeanPostProcessor接口postProcessBeforeInitialization()方法,可对初始化前的Bean实例进行拦截
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
      Object current = processor.postProcessBeforeInitialization(result, beanName);
      if (current == null) {
        return result;
      }
      result = current;
    }
    return result;
  }
//*****扩展点*********扩展点*********扩展点*********扩展点*********扩展点****
// 初始化Bean的三种方式:
// 1.实现InitializingBean接口afterPropertiesSet()
// 2.@PostConstruct注解
// 3.xml配置init-method属性
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
      throws Throwable {
  // 调用InitializingBean接口afterPropertiesSet()初始化
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
      if (logger.isTraceEnabled()) {
        logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
      }
      if (System.getSecurityManager() != null) {
        try {
          AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
            ((InitializingBean) bean).afterPropertiesSet();
            return null;
          }, getAccessControlContext());
        }
        catch (PrivilegedActionException pae) {
          throw pae.getException();
        }
      }
      else {
        ((InitializingBean) bean).afterPropertiesSet();
      }
    }
  // 调用init-method指定的方法;就是反射执行
  // @PostConstruct注解在上面applyMergedBeanDefinitionPostProcessors()扩展BeanDefinition的时候被解析后设置到BeanDefinition中去了,可查看InitDestroyAnnotationBeanPostProcessor
    if (mbd != null && bean.getClass() != NullBean.class) {
      String initMethodName = mbd.getInitMethodName();
      if (StringUtils.hasLength(initMethodName) &&
          !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
          !mbd.isExternallyManagedInitMethod(initMethodName)) {
        invokeCustomInitMethod(beanName, bean, mbd);
      }
    }
  }
@Override
  public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {
    Object result = existingBean;
    // AOP入口
    // *****扩展点*********扩展点*********扩展点*********扩展点*********扩展点****
    // 实现BeanPostProcessor接口postProcessAfterInitialization()方法,可对初始化前的Bean实例进行拦截
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
      Object current = processor.postProcessAfterInitialization(result, beanName);
      if (current == null) {
        return result;
      }
      result = current;
    }
    return result;
  }
复制代码

注册销毁方法

// *****扩展点*********扩展点*********扩展点*********扩展点*********扩展点****
// 销毁方法有三种:
// 1.实现DisposableBean接口的destroy()方法
// 2.@PreDestroy注解
// 3.xml配置destroy-method
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
    AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
    if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
      if (mbd.isSingleton()) {
        // Register a DisposableBean implementation that performs all destruction
        // work for the given bean: DestructionAwareBeanPostProcessors,
        // DisposableBean interface, custom destroy method.
        // 注册实现了DisposableBean接口
        registerDisposableBean(beanName,
            new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
      }
      else {
        // 针对destroy-method配置;其实@PreDestroy注解会在applyMergedBeanDefinitionPostProcessors()扩展BeanDefinition的时候被解析后设置到BeanDefinition中去了,可查看InitDestroyAnnotationBeanPostProcessor
        // A bean with a custom scope...
        Scope scope = this.scopes.get(mbd.getScope());
        if (scope == null) {
          throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
        }
        scope.registerDestructionCallback(beanName,
            new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
      }
    }
  }
复制代码

总结一下:getBean()

  • doGetBean()1.先从缓存中获取
  • getSingleton():看看缓存中是否有Bean对象;逐步从一级缓存、二级缓存、三级缓存中取;这个要和Bean实例化后addSingleton()结合起来看;这个getSingleton()是可以从三级缓存中创建代理对象的。
  • getObjectForBeanInstance():如果是以“&”开头的beanName,那么就返回FactoryBean对象;否则,如果这个Bean对象不是FactoryBean的话,就直接返回;如果是FactoryBean,那么就调用FactoryBean的getObject()返回目标对象。
    2.从父容器中获取
  • 如果上面的getSingleton()获取不到Bean对象,那么就要从父容器中getBean()
    3.创建DependsOn对象
  • 如果没有父容器或者父容器也拿不到Bean对象,那么就先计算该目标对象的DependsOn,也就是依赖,看看有哪些Bean是需要在这个对象创建之前要创建的。也是通过getBean()触发创建逻辑。
    4.创建Bean对象
  • 最后就是getSingleton()逻辑中执行创建Bean的逻辑;里面会有一个ObjectFactory,里面最终调用的是createBean方法创建Bean。创建好的Bean最终被添加到一级缓存中。4.1:前置InstantiationAwareBeanPostProcessor
  • resolveBeforeInstantiation():在Bean实例化之前,给出扩展点让开发者自己有机会创建Bean实例。可用于AOP切入创建代理对象。
  • 4.2:真正的创建Bean实例
  • doCreateBean():这里面完成了Bean的创建、BeanDefinition的扩展、AOP的切入、属性值的设置、初始化的执行、销毁方法的注册4.2.1:创建Bean实例
  • createBeanInstance():分别通过工厂方法、有参构造、无参构造、反射等方法创建Bean实例
  • obtainFromSupplier():工厂方法
  • instantiateUsingFactoryMethod():工厂方法,factory-method配置。静态工厂、实例工厂。
  • autowireConstructor():有参构造、无参构造
  • instantiateBean():默认反射
  • 4.2.2:BeanDefinition的扩展
  • applyMergedBeanDefinitionPostProcessors():MergedBeanDefinitionPostProcessor实现类可以重新设置BeanDefinition。这里最直接的应用就是针对@Autowired、@Value、@Inject注解
  • 4.2.3:AOP的切入
  • addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)):这个就是把刚刚创建出来、还没有对属性赋值的Bean实例放到三级缓存中,给它指定SmartInstantiationAwareBeanPostProcessor子类增强。也就是说,在这个阶段实现SmartInstantiationAwareBeanPostProcessor,就可以针对目标Bean创建Proxy代理。
  • 4.2.4:属性值的设置
  • populateBean():设置属性值。这里面同样也会去IOC容器中找属性对应的Bean实例。在这里的话,也有一个扩展点,就是InstantiationAwareBeanPostProcessor子类可以自定义是否交由spring设置属性值、修改指定的属性值。
  • 4.2.5:初始化的执行
  • initializeBean():这里面就是开始准备初始化的生命周期了。执行Aware接口逻辑、BeforeInitialization、执行初始化方法、AfterInitialization等逻辑的执行。
  • invokeAwareMethods():分别调用BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
  • applyBeanPostProcessorsBeforeInitialization():调用BeanPostProcessor的postProcessBeforeInitialization方法;AOP的织入点
  • invokeInitMethods():调用InitializingBean.afterPropertiesSet(),@PostConstruct注解方法,Init-method配置的目标方法
  • applyBeanPostProcessorsAfterInitialization():调用BeanPostProcessor的postProcessAfetrInitialization方法;AOP的织入点
  • 4.2.6:销毁方法的注册
  • registerDisposableBeanIfNecessary():调用DisposableBean的实现类,@PreDestory注解的方法,destory-method配置的目标方法
  • getObjectForBeanInstance():如果是以“&”开头的beanName,那么就返回FactoryBean对象;否则,如果这个Bean对象不是FactoryBean的话,就直接返回;如果是FactoryBean,那么就调用FactoryBean的getObject()返回目标对象。


相关文章
|
4天前
|
存储 Java 数据库
Spring的使用-Bean对象的储存和获取/Bea对象的作用域与生命周期
Spring的使用-Bean对象的储存和获取/Bea对象的作用域与生命周期
|
9天前
|
Java Spring 容器
Spring注解开发,bean的作用范围及生命周期、Spring注解开发依赖注入
Spring注解开发,bean的作用范围及生命周期、Spring注解开发依赖注入
21 1
Spring注解开发,bean的作用范围及生命周期、Spring注解开发依赖注入
|
9天前
|
Java 容器 Spring
Spring的加载配置文件、容器和获取bean的方式
Spring的加载配置文件、容器和获取bean的方式
20 3
Spring的加载配置文件、容器和获取bean的方式
|
9天前
|
Java Spring 容器
Spring核心概念、IoC和DI的认识、Spring中bean的配置及实例化、bean的生命周期
Spring核心概念、IoC和DI的认识、Spring中bean的配置及实例化、bean的生命周期
27 0
|
9天前
|
XML Java 数据格式
Spring框架学习 -- Bean的生命周期和作用域
Spring框架学习 -- Bean的生命周期和作用域
16 2
|
9天前
|
存储 XML Java
Spring框架学习 -- 读取和存储Bean对象
Spring框架学习 -- 读取和存储Bean对象
13 0
Spring框架学习 -- 读取和存储Bean对象
|
18天前
|
XML 前端开发 Java
【JavaEE】深入了解Spring中Bean的可见范围(作用域)以及前世今生(生命周期)
【JavaEE】深入了解Spring中Bean的可见范围(作用域)以及前世今生(生命周期)
17 0
|
18天前
|
存储 缓存 Java
【JavaEE】Spring中注解的方式去获取Bean对象
【JavaEE】Spring中注解的方式去获取Bean对象
4 0
|
18天前
|
存储 Java 对象存储
【JavaEE】Spring中注解的方式去存储Bean对象
【JavaEE】Spring中注解的方式去存储Bean对象
13 0
|
18天前
|
存储 Java 对象存储
【JavaEE】DI与DL的介绍-Spring项目的创建-Bean对象的存储与获取
【JavaEE】DI与DL的介绍-Spring项目的创建-Bean对象的存储与获取
11 0