欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring生命周期简介与具体应用

程序员文章站 2022-05-04 08:56:53
Spring对Bean进行实例化(相当于程序中的new Xx())Spring将值和Bean的引用注入进Bean对应的属性中如果Bean实现了BeanNameAware接口,Spring将Bean的ID传递给setBeanName()方法(实现BeanNameAware主要是为了通过Bean的引用来获得Bean的ID,一般业务中是很少有用到Bean的ID的)如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanDactory(BeanFactory bf)方法并把.....

Spring生命周期简介与具体应用

  1. Spring对Bean进行实例化(相当于程序中的new Xx())
  2. Spring将值和Bean的引用注入进Bean对应的属性中
  3. 如果Bean实现了BeanNameAware接口,Spring将Bean的ID传递给setBeanName()方法(实现BeanNameAware主要是为了通过Bean的引用来获得Bean的ID,一般业务中是很少有用到Bean的ID的)
  4. 如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanDactory(BeanFactory bf)方法并把BeanFactory容器实例作为参数传入。(实现BeanFactoryAware 主要目的是为了获取Spring容器,如Bean通过Spring容器发布事件等)
  5. 如果Bean实现了ApplicationContextAware接口,Spring容器将调用setApplicationContext(ApplicationContext ctx)方法,把应用上下文作为参数传入.
    (作用与BeanFactory类似都是为了获取Spring容器,不同的是Spring容器在调用setApplicationContext方法时会把它自己作为setApplicationContext 的参数传入,而Spring容器在调用setBeanFactory前需要程序员自己指定(注入)setBeanFactory里的参数BeanFactory )
  6. 如果Bean实现了BeanPostProcess接口,Spring将调用它们的postProcessBeforeInitialization(预初始化)方法(作用是在Bean实例创建成功后对进行增强处理,如对Bean进行修改,增加某个功能)
  7. 如果Bean实现了InitializingBean接口,Spring将调用它们的afterPropertiesSet方法,作用与在配置文件中对Bean使用init-method声明初始化的作用一样,都是在Bean的全部属性设置成功后执行的初始化方法。
  8. 如果Bean实现了BeanPostProcess接口,Spring将调用它们的postProcessAfterInitialization(后初始化)方法
    (作用与6的一样,只不过6是在Bean初始化前执行的,而这个是在Bean初始化后执行的,时机不同 )
  9. 如果是单例的bean,则将该bean放入singleTonOnject池中,下一次再用的时候直接取
  10. 经过以上的工作后,Bean将一直驻留在应用上下文中给应用使用,直到应用上下文被销毁
  11. 如果Bean实现了DispostbleBean接口,Spring将调用它的destory方法,作用与在配置文件中对Bean使用destory-method属性的作用一样,都是在Bean实例销毁前执行的方法。

在其中:
4能获取BeanFactory(DefaultListableBeanFactory),5能获取ApplicationContext(DefaultListableBeanFactory)
你会发现,他们获取的都是同一个!

@Component
public class BeanFactoryUtil implements BeanFactoryAware {
    private static BeanFactory beanFactory;

    public static BeanFactory getBeanFactory() {
        return beanFactory;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        System.out.println("调用了setBeanFactory");
        setFactory(beanFactory);
    }

    private static void setFactory(BeanFactory bf) {
        beanFactory = bf;
    }
}


@SpringBootTest
class BeanFactoryUtilTest {

    @Test
    void getBeanFactory() {
        System.out.println("===========" + BeanFactoryUtil.getBeanFactory().getClass().getSimpleName());
    }
}
@Component
public class ApplicationContextUtil implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(@NotNull ApplicationContext context) {
        System.out.println("调用了setApplicationContext");
        setContext(context);
    }

    private static void setContext(@NotNull ApplicationContext ac) {
        context = ac;
    }

    public static ApplicationContext getContext() {
        return context;
    }
}

@SpringBootTest
class ApplicationContextUtilTest {

    @Test
    void getContext() {
        System.out.println("===========" + ApplicationContextUtil.getContext().getClass().getSimpleName());
    }
}

这个DefaultListableBeanFactory可以理解为整个spring IOC容器的始祖

6和8的话能做一个bean实例化之后的操作,比如动态代理:

public interface BeanPostProcessor {
	// 这个方法会在bean实例化后,调用初始化方法之前执行
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
    // 这个方法会在bean实例化后,调用初始化方法之后执行
    // 这里的before和after是相对于初始化方法的调用
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
}

我们知道往往大哥注解就可以让一个普通的类在运行时期变成动态代理类,比如说@Transcational
本来是一个普通的bean,然后在运行期的某个时刻就变成了动态代理bean,有可能就是BeanPostProcessor做了这方面的事情
我们查看BeanPostProcessor的实现类:
Spring生命周期简介与具体应用
发现有一个实现类好像和我们的aop有关:AbstractAutoProxyCreator
Spring生命周期简介与具体应用
差不多就是这个意思,判断某个bean是否需要被代理,需要被代理的就会动态代理创建出来,
其中:

	/**
     * 如果子类将bean标识为一个要代理的bean,则使用配置的拦截器创建一个代理。
	 * @see #getAdvicesAndAdvisorsForBean
	 */
	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}


	/**
	 * 必要时包装给定的bean,如果他资格被代理。
	 */
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

最终动态代理在createProxy方法中proxyFactory.getProxy(getProxyClassLoader())执行

这里有BeanPostProcessor的一个小应用可以看看:Spring源码分析(五) – Spring中的BeanPostProcessor

其他详细的使用就不在这里介绍了

本文地址:https://blog.csdn.net/qq_39327985/article/details/107357290