Spring源码:Bean生命周期(四)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 在本文中,我们深入探讨了 Spring 框架中 Bean 的实例化过程,关于某些细节以后我会单独拿出一篇文章单独讲解,我们来总结下实例化都做了哪些事情:先从bean定义中加载当前类,因为最初Spring使用ASM技术解析元数据时只获取了当前类的名称寻找所有InstantiationAwareBeanPostProcessors实现类,并调用实例化前的方法postProcessBeforeInstantiation进行实例化,这里会使用构造方法进行实例化调用applyMergedBeanDefinitionPostProcessors找到所有MergedBeanDefinitionPostPro

前言

在之前的文章中,我们介绍了 Bean 的核心概念、Bean 定义的解析过程以及 Bean 创建的准备工作。在今天的文章中,我们将深入探讨 Bean 的创建过程,并主要讲解 createBean 方法的实现。在这个过程中,我们将了解 Bean 的实例化、属性注入、初始化和销毁等步骤,以及各个步骤的具体实现细节。通过本文的学习,读者将能够更深入地理解 Spring 框架中 Bean 的创建过程,从而为后续的学习和实践打下坚实的基础。好了,我们开始!

createBean

前面我们说过,最开始的bean定义(合并后的),解析类的元数据时,用到的是ASM技术并不会真正开始解析class文件,所以也只是提取出来bean的name值作为beanClass属性,知道这个前提,那么这一步就好说了,下面是他的源码:

    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {
   

        RootBeanDefinition mbdToUse = mbd;

        // 马上就要实例化Bean了,确保beanClass被加载了
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
   
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        // Prepare method overrides.
        try {
   
            mbdToUse.prepareMethodOverrides();
        }

        try {
   
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            // 实例化前
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
   
                return bean;
            }
        }

        try {
   
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            ......
            return beanInstance;
        }
    }
  1. resolveBeanClass:真正的开始加载bean。
  2. mbdToUse.prepareMethodOverrides();和@lookUp注解有关系,不看
  3. resolveBeforeInstantiation:实例化前的BeanPostProcessors,如果初始化了那么就返回了,不走其他创建逻辑了。
  4. doCreateBean:正常开始实例化、初始化bean。

resolveBeanClass

如果当前bean被加载了,那么直接返回了,如果没加载那么开始解析当前bean

    @Nullable
    protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
            throws CannotLoadBeanClassException {
   

        try {
   
            // 如果beanClass被加载了
            if (mbd.hasBeanClass()) {
   
                return mbd.getBeanClass();
            }

            // 如果beanClass没有被加载
            if (System.getSecurityManager() != null) {
   
                return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)
                        () -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
            }
            else {
   
                return doResolveBeanClass(mbd, typesToMatch);
            }
        }
    }

是否已经加载的判断依据就是我说的,是否是class,正常下我们的beanClass为字符串,也就是beanname,看下源码:

public boolean hasBeanClass() {
   
        return (this.beanClass instanceof Class);
    }

doResolveBeanClass

真正开始加载class,如果需要加载class那肯定离不开类加载器,看下源码:

    @Nullable
    private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
            throws ClassNotFoundException {
   

        ClassLoader beanClassLoader = getBeanClassLoader();
        ClassLoader dynamicLoader = beanClassLoader;
        boolean freshResolve = false;

        if (!ObjectUtils.isEmpty(typesToMatch)) {
   
            // When just doing type checks (i.e. not creating an actual instance yet),
            // use the specified temporary class loader (e.g. in a weaving scenario).
            ClassLoader tempClassLoader = getTempClassLoader();
            if (tempClassLoader != null) {
   
                dynamicLoader = tempClassLoader;
                freshResolve = true;
                if (tempClassLoader instanceof DecoratingClassLoader) {
   
                    DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
                    for (Class<?> typeToMatch : typesToMatch) {
   
                        dcl.excludeClass(typeToMatch.getName());
                    }
                }
            }
        }

        String className = mbd.getBeanClassName();
        if (className != null) {
   
            // 解析Spring表达式,有可能直接返回了一个Class对象
            Object evaluated = evaluateBeanDefinitionString(className, mbd);
            if (!className.equals(evaluated)) {
   
                // A dynamically resolved expression, supported as of 4.2...
                if (evaluated instanceof Class) {
   
                    return (Class<?>) evaluated;
                }
                else if (evaluated instanceof String) {
   
                    className = (String) evaluated;
                    freshResolve = true;
                }
                else {
   
                    throw new IllegalStateException("Invalid class name expression result: " + evaluated);
                }
            }
            if (freshResolve) {
   
                // When resolving against a temporary class loader, exit early in order
                // to avoid storing the resolved Class in the bean definition.
                if (dynamicLoader != null) {
   
                    try {
   
                        return dynamicLoader.loadClass(className);
                    }
                    catch (ClassNotFoundException ex) {
   
                        if (logger.isTraceEnabled()) {
   
                            logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
                        }
                    }
                }
                return ClassUtils.forName(className, dynamicLoader);
            }
        }

        // Resolve regularly, caching the result in the BeanDefinition...
        return mbd.resolveBeanClass(beanClassLoader);
    }

我们自己的bean走不了这么多逻辑,我们既没有传typesToMatch,也没有写Spring表达式,所以就是拿了一个类加载器和使用类加载器加载class,如果我们没有自定义类加载器那么使用默认的,看下源码:

    @Nullable
    public static ClassLoader getDefaultClassLoader() {
   
        ClassLoader cl = null;

        // 优先获取线程中的类加载器
        try {
   
            cl = Thread.currentThread().getContextClassLoader();
        }
        catch (Throwable ex) {
   
            // Cannot access thread context ClassLoader - falling back...
        }

        // 线程中类加载器为null的情况下,获取加载ClassUtils类的类加载器
        if (cl == null) {
   
            // No thread context class loader -> use class loader of this class.
            cl = ClassUtils.class.getClassLoader();
            if (cl == null) {
   
                // getClassLoader() returning null indicates the bootstrap ClassLoader
                // 加入ClassUtils是被Bootstrap类加载器加载的,则获取系统类加载器
                try {
   
                    cl = ClassLoader.getSystemClassLoader();
                }
                catch (Throwable ex) {
   
                    // Cannot access system ClassLoader - oh well, maybe the caller can live with null...
                }
            }
        }
        return cl;
    }
  1. 优先获取线程中的类加载器
  2. 线程中类加载器为null的情况下,获取加载ClassUtils类的类加载器,这里Spring注意到了java的boostrap加载器,所以会有为null的情况
  3. 如果为null,那么使用ClassUtils当前工具类使用的是哪个加载器
  4. 假如ClassUtils是被Bootstrap类加载器加载的,则获取系统类加载器
    public Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {
   
        String className = getBeanClassName();
        if (className == null) {
   
            return null;
        }
        Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
        this.beanClass = resolvedClass;
        return resolvedClass;
    }
    public String getBeanClassName() {
   
        Object beanClassObject = this.beanClass;
        if (beanClassObject instanceof Class) {
   
            return ((Class<?>) beanClassObject).getName();
        }
        else {
   
            return (String) beanClassObject;
        }
    }

通过这一步也可以看出bean定义中最初的beanClass属性,都是String类型的beanname

resolveBeforeInstantiation

这一步走的是实例化前的工作,当然如果你想在这一步中直接返回实体类也可,而且最离谱的是Spring并没有校验你返回的类是否是当前beanname的类,可以看下源码:

    @Nullable
    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
   
        Object bean = null;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
   
            // Make sure bean class is actually resolved at this point.
            // synthetic表示合成,如果某些Bean式合成的,那么则不会经过BeanPostProcessor的处理
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
   
                Class<?> targetType = determineTargetType(beanName, mbd);
                if (targetType != null) {
   
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
   
                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }
            mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
    }
  1. hasInstantiationAwareBeanPostProcessors:直接从缓存list中获取有关实例化的BeanPostProcessors,这里是一个优化,要不然每次获取有关实例化的BeanPostProcessors都是遍历整个BeanPostProcessors再加个校验
  2. determineTargetType:获取类
  3. applyBeanPostProcessorsBeforeInstantiation:执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation的方法,该方法可以返回bean。
  4. postProcessAfterInstantiation:执行BeanPostProcessor的postProcessAfterInstantiation的方法,正常我们的bean不会走到这里,因为实例化前根本没有创建出来bean,所以也就是bean != null一直为false

当然除非你自己写一个InstantiationAwareBeanPostProcessors,其实真没看见这么玩的,主要是没有啥意义,比如这样:

@Component
public class MyInstantiationAwareBeanPostProcessors implements InstantiationAwareBeanPostProcessor {
   

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
   
        if (beanName.equals("userService")) {
   
            System.out.println("MyInstantiationAwareBeanPostProcessors.postProcessBeforeInstantiation");
            return new First();
        }
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
   
        if (beanName.equals("userService")) {
   
            System.out.println("MyInstantiationAwareBeanPostProcessors.postProcessAfterInitialization");
            return new Second();
        }
        return bean;
    }
}

再坚持一下,让我把实例化过程先讲完!

现在的逻辑已经走完了实例化前的postProcessBeforeInstantiation方法,那么现在我们的bean要进行实例化了,

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {
   

        // 实例化bean
        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
   
            // 有可能在本Bean创建之前,就有其他Bean把当前Bean给创建出来了(比如依赖注入过程中)
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
   
            // 创建Bean实例
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
   
            mbd.resolvedTargetType = beanType;
        }

        // 后置处理合并后的BeanDefinition
        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
   
            if (!mbd.postProcessed) {
   
                try {
   
                    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.
        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");
            }
            // 循环依赖-添加到三级缓存
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
   
            // 属性填充
            populateBean(beanName, mbd, instanceWrapper);
      ......
        return exposedObject;
    }

跟这篇无关的内容能删除的都删除了,主要有这几步我们需要注意下:

  1. createBeanInstance:创建实例,前提是之前没有创建过
  2. applyMergedBeanDefinitionPostProcessors:找到注入点,比如AutowiredAnnotationBeanPostProcessor(@Autowired、@Value、@Inject)和CommonAnnotationBeanPostProcessor(@Resource),这在实例化前和实例化后方法中间夹了一个处理合并bean定义的逻辑,注意一下
  3. addSingletonFactory:添加缓存,用来解决循环依赖,以后单独讲解
  4. populateBean:这一方法主要是属性填充也就是依赖注入的,但是官方把实例化后的PostProcessors方法写到这里了,所以也得贴出来,但是我们只看实例化相关的。

createBeanInstance

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
   
        // Make sure bean class is actually resolved at this point.
        Class<?> beanClass = resolveBeanClass(mbd, beanName);

        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());
        }

        // BeanDefinition中添加了Supplier,则调用Supplier来得到对象
        Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
        if (instanceSupplier != null) {
   
            return obtainFromSupplier(instanceSupplier, beanName);
        }

        // @Bean对应的BeanDefinition
        if (mbd.getFactoryMethodName() != null) {
   
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }
    ......
        return instantiateBean(beanName, mbd);
    }
  1. resolveBeanClass:之前讲解过了,不重复讲了,就是拿到class
  2. obtainFromSupplier:通过Supplier函数获取bean,前提是你得声明bean定义
  3. instantiateUsingFactoryMethod:这种是使用@Bean方法实例化对象,
  4. 后面省略了推断构造方法进行实例化对象,以后单独讲解推断构造方法

obtainFromSupplier

这一步其实我们用到的很少,主要是考虑到Spring自动注入的开销,我们自己可以就行实例化而已,比如我们这样写照样可以获取bean,但是不会由Spring帮我们注入,得靠自己了:

//         创建一个Spring容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        beanDefinition.setBeanClass(UserService.class);
        beanDefinition.setInstanceSupplier(() -> new UserService());
        applicationContext.registerBeanDefinition("userService", beanDefinition);
        UserService userService = (UserService) applicationContext.getBean(UserService.class);
        userService.test();

其实用法和@bean注解相似,除了减少Spring自动注入的开销,实在没想到有啥用

instantiateUsingFactoryMethod

该方法内部逻辑很多,为了更加直观的展现,只贴出关键代码:

    @Override
    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
            @Nullable Object factoryBean, final Method factoryMethod, Object... args) {
   

        try {
   
            if (System.getSecurityManager() != null) {
   
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
   
                    ReflectionUtils.makeAccessible(factoryMethod);
                    return null;
                });
            }
            else {
   
                ReflectionUtils.makeAccessible(factoryMethod);
            }

            Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
            try {
   
                currentlyInvokedFactoryMethod.set(factoryMethod);
                // factoryBean就是AppConfig的代理对象(如果加了@Configuration)
                // factoryMethod就是@Bean修饰的方法
                Object result = factoryMethod.invoke(factoryBean, args);
                if (result == null) {
   
                    result = new NullBean();
                }
                return result;
            }
            finally {
   
                if (priorInvokedFactoryMethod != null) {
   
                    currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
                }
                else {
   
                    currentlyInvokedFactoryMethod.remove();
                }
            }
        }
        ......
    }

比如我们定义的配置类中有很多@Bean形式的方法,最终Spring会直接invoke调用被@Bean修饰的方法从而实现实例化对象。

applyMergedBeanDefinitionPostProcessors

这里关于MergedBeanDefinitionPostProcessors的实现类不全讲解了,主要讲解下工作常用的注解AutowiredAnnotationBeanPostProcessor,他是用来解析@Autowired、@Value、@Inject,看下他的默认源码:

public AutowiredAnnotationBeanPostProcessor() {
   
        this.autowiredAnnotationTypes.add(Autowired.class);
        this.autowiredAnnotationTypes.add(Value.class);
        try {
   
            this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
                    ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
        }
    }

看下他主要做了那些工作,关键代码附上:

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
   
    // 如果一个Bean的类型是String...,那么则根本不需要进行依赖注入
    if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
   
        return InjectionMetadata.EMPTY;
    }

    List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    Class<?> targetClass = clazz;

    do {
   
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

        // 遍历targetClass中的所有Field
        ReflectionUtils.doWithLocalFields(targetClass, field -> {
   
            // field上是否存在@Autowired、@Value、@Inject中的其中一个
            MergedAnnotation<?> ann = findAutowiredAnnotation(field);
            if (ann != null) {
   
                // static filed不是注入点,不会进行自动注入
                if (Modifier.isStatic(field.getModifiers())) {
   
                    if (logger.isInfoEnabled()) {
   
                        logger.info("Autowired annotation is not supported on static fields: " + field);
                    }
                    return;
                }

                // 构造注入点
                boolean required = determineRequiredStatus(ann);
                currElements.add(new AutowiredFieldElement(field, required));
            }
        });

        // 遍历targetClass中的所有Method
        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
   

            Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
            if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
   
                return;
            }
            // method上是否存在@Autowired、@Value、@Inject中的其中一个
            MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
            if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
   
                // static method不是注入点,不会进行自动注入
                if (Modifier.isStatic(method.getModifiers())) {
   
                    if (logger.isInfoEnabled()) {
   
                        logger.info("Autowired annotation is not supported on static methods: " + method);
                    }
                    return;
                }
                // set方法最好有入参
                if (method.getParameterCount() == 0) {
   
                    if (logger.isInfoEnabled()) {
   
                        logger.info("Autowired annotation should only be used on methods with parameters: " +
                                    method);
                    }
                }
                boolean required = determineRequiredStatus(ann);
                PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                currElements.add(new AutowiredMethodElement(method, required, pd));
            }
        });

        elements.addAll(0, currElements);
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);

    return InjectionMetadata.forElements(elements, clazz);
}
  1. 如果一个Bean的类型是String,那么则根本不需要进行依赖注入
  2. 遍历targetClass中的所有Field,是否存在@Autowired、@Value、@Inject中的其中一个,如果是static字段则不注入否则记录构造注入点
  3. 遍历targetClass中的所有Method,是否存在@Autowired、@Value、@Inject中的其中一个,如果是static字段则不注入否则记录构造注入点

populateBean

这个方法主要是属性填充,也就是所说的依赖注入的过程,我们不讲解这一部分,只讲解关于实例化最后的阶段postProcessAfterInstantiation方法,方法进来第一步就是调用postProcessAfterInstantiation方法。但是只看Spring源码的话,其实并没有太多实现,都是默认实现方法:

        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
   
            for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
   
                if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
   
                    return;
                }
            }
        }

总结

在本文中,我们深入探讨了 Spring 框架中 Bean 的实例化过程,关于某些细节以后我会单独拿出一篇文章单独讲解,我们来总结下实例化都做了哪些事情:

  1. 先从bean定义中加载当前类,因为最初Spring使用ASM技术解析元数据时只获取了当前类的名称
  2. 寻找所有InstantiationAwareBeanPostProcessors实现类,并调用实例化前的方法postProcessBeforeInstantiation
  3. 进行实例化,这里会使用构造方法进行实例化
  4. 调用applyMergedBeanDefinitionPostProcessors找到所有MergedBeanDefinitionPostProcessors的实现类,比如我们的注入点(@Autowired等)
  5. 寻找所有InstantiationAwareBeanPostProcessors实现类,并调用实例化后的方法postProcessAfterInstantiation

通过本文的学习,读者将能够更深入地了解 Spring 框架中 Bean 的实例化过程,为后续的学习和实践打下坚实的基础。下一篇文章,我们将深入探讨 Bean 的初始化过程。

相关文章
|
25天前
|
XML 安全 Java
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
77 2
|
1天前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
1天前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
7天前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
37 6
|
9天前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
56 3
|
23天前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
44 2
|
22天前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
32 1
|
6月前
|
Java 开发者 Spring
解析Spring中Bean的生命周期
解析Spring中Bean的生命周期
60 2
|
6月前
|
XML druid Java
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
73 0