当前位置: 代码迷 >> 综合 >> # Spring IOC容器:BeanFactory、ApplicationContext和Bean的加载
  详细解决方案

# Spring IOC容器:BeanFactory、ApplicationContext和Bean的加载

热度:100   发布时间:2023-10-31 20:12:00.0

Spring IOC容器:BeanFactory、ApplicationContext和Bean的加载

Spring IOC概念

简单来说就是创建实例的操作由Spring完成,使用的时候直接拿来用就行了。举个例子一般实例化一个对象会进行new操作,而Spring中new操作有Spring完成。


BeanFactory容器

在 Spring 中,BeanFactory是 IoC 容器的核心接口。它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。。BeanFactory是基础类型的IOC容器。它在org.springframework.beans.factory.BeanFactory接口定义,提供Bean的注册。BeanFactory接口的使用有ApplicationContext继承类和BeanFactory实现类。

BeanFactory接口源码
public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";Object getBean(String var1) throws BeansException;<T> T getBean(String var1, Class<T> var2) throws BeansException;Object getBean(String var1, Object... var2) throws BeansException;<T> T getBean(Class<T> var1) throws BeansException;<T> T getBean(Class<T> var1, Object... var2) throws BeansException;<T> ObjectProvider<T> getBeanProvider(Class<T> var1);<T> ObjectProvider<T> getBeanProvider(ResolvableType var1);boolean containsBean(String var1);boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;@NullableClass<?> getType(String var1) throws NoSuchBeanDefinitionException;String[] getAliases(String var1);
}
BeanFactory主要实现类
  • StaticListableBeanFactory:StaticListableBeanFactory实现ListableBeanFactory,ListableBeanFactory继承BeanFactory接口。StaticListableBeanFactory不包括bean的实例化过程。需要手动add操作注册bean。
  • DefaultListableBeanFactory:BeanFactory的默认实现。
@Test
public void test1(){
    // 定义Bean的文件地址ClassPathResource resource=new ClassPathResource("HelloWorld.xml");DefaultListableBeanFactory factory=new DefaultListableBeanFactory();XmlBeanDefinitionReader reader=new XmlBeanDefinitionReader(factory);reader.loadBeanDefinitions(resource);HelloWorld helloWorld = factory.getBean(HelloWorld.class);System.out.println(helloWorld.toString());
}
  • XmlBeanFactory:从xml中配置元数据。
@Test
public void test7(){
    Resource resource = new ClassPathResource("HelloWorld.xml");BeanFactory beanFactory = new XmlBeanFactory(resource);HelloWorld helloWorld = beanFactory.getBean(HelloWorld.class);System.out.println(helloWorld.toString());
}

FactoryBean接口

Spring 中为提供了两种类型的 bean,一种就是普通的 bean,我们通过 getBean(id) 方法获得是该 bean 的实际类型,另外还有一种 bean 是 FactoryBean,这个bean可以生产别的bean,我们通过 getBean(id) 获得是该工厂所产生的 Bean 的实例,而不是该 FactoryBean 的实例。实现Factory接口的类可以改变bean。

FactoryBean实现demo
  • HelloWorldFactoryBean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><bean id="helloFactoryBean" class="com.li.test.factorybean.HelloFactoryBean" ><property name="message" value="张三" ></property><property name="id" value="1"></property></bean></beans>
  • HelloFactoryBean
// 实现FactoryBean接口重写三个方法
public class HelloFactoryBean implements FactoryBean<HelloWorld> {
    private int id;private String message;@Overridepublic HelloWorld getObject() throws Exception {
    // 在这里可以对生成的Bean实例进行操作return new HelloWorld(id,"李四");}@Overridepublic Class<?> getObjectType() {
    // 定义生成bean的类型return HelloWorld.class;}/*** 工厂所管理的对象是否为单例的* 即如果该方法返回true,那么通过getObject()方法返回的对象都是同一个对象*/@Overridepublic boolean isSingleton() {
    return true;}public int getId() {
    return id;}public void setId(int id) {
    this.id = id;}public String getMessage() {
    return message;}public void setMessage(String message) {
    this.message = message;}
}
  • Test
 @Test
public void test1(){
    BeanFactory beanFactory = new ClassPathXmlApplicationContext("HelloWorldFactoryBean.xml");HelloWorld helloWorld = (HelloWorld) beanFactory.getBean("helloFactoryBean");System.out.println(helloWorld.toString());
}
// 输出:HelloWorld{id=1, message='李四'} 发现message变化了。

ApplicationContext容器

ApplicationContextBeanFactory的子接口,也被称为Spring上下文。Application Context 是 spring 中较高级的容器。和 BeanFactory 类似,它可以加载配置文件中定义的 bean,将所有的 bean 集中在一起,当有请求的时候分配 bean。

ApplicationContext常用实现类
  • ClassPathXmlApplicationContext:从类路径 ClassPath 中寻找指定的 XML 配置文件,找到并装载完成 ApplicationContext 的实例化工作。
@Test
public void test3(){
    AbstractApplicationContext context=new ClassPathXmlApplicationContext("HelloWorld.xml");HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");System.out.println(helloWorld);context.registerShutdownHook();
}
  • FileSystemXmlApplicationContext:类从指定的文件系统路径中寻找指定的 XML 配置文件,找到并装载完成 ApplicationContext 的实例化工作。

Spring Bean工厂准备(Bean被定义)

Spring入口
@Test
public void test4(){
    ApplicationContext context=new ClassPathXmlApplicationContext("AopXmlBeans.xml");Message message = (Message) context.getBean("message");message.getId();message.getMessage();message.showMessage();
}
new ClassPathXmlApplication()之后发生了什么?
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
    this(configLocations, refresh, null);
}public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)throws BeansException {
    super(parent);// 初始化容器中bean的配置信息setConfigLocations(configLocations);if (refresh) {
    refresh();}
}
重点方法refresh()
  • 看看这个refresh()方法是什么?这个方法在抽象public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext类中。这个方法至关重要:
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
    // 为刷新做好准备prepareRefresh();// 告诉子类刷新内部bean工厂。ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 准备在此上下文中使用的bean工厂。prepareBeanFactory(beanFactory);try {
    // 允许在上下文子类中对bean工厂进行后处理。postProcessBeanFactory(beanFactory);// 调用作为上下文中的bean注册的工厂处理器。invokeBeanFactoryPostProcessors(beanFactory);// 注册拦截bean创建的bean处理器。registerBeanPostProcessors(beanFactory);// 初始化此上下文的消息源。initMessageSource();// 为此上下文初始化事件多播程序。initApplicationEventMulticaster();// 在特定的上下文子类中初始化其他特殊bean。onRefresh();// 检查侦听器bean并注册它们。registerListeners();// 实例化所有剩余的(非lazy-init)单例。finishBeanFactoryInitialization(beanFactory);// 最后一步:发布相应的事件。finishRefresh();}catch (BeansException ex) {
    if (logger.isWarnEnabled()) {
    logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// 销毁已经创建的单例,以避免悬浮资源。destroyBeans();// 重置“活跃”的旗帜。cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {
    // 在Spring的核心中重置公共自省缓存resetCommonCaches();}}
}
  • prepareRefresh():容器刷新前的准备、设置上下文状态、获取属性等。
  • onfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory():获取新的beanFactory,销毁原有beanFactory、为每个bean生成BeanDefinition等。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 刷新上下文环境、销毁原有创建新的beanFactoryrefreshBeanFactory();return getBeanFactory();
}

refreshBeanFactory():如果beanfactory存在,则销毁然后再创建新的beanfactory。

@Override
protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
    // 销毁beandestroyBeans();closeBeanFactory();}try {
    // 创建新的beanFactoryDefaultListableBeanFactory beanFactory = createBeanFactory();beanFactory.setSerializationId(getId());customizeBeanFactory(beanFactory);loadBeanDefinitions(beanFactory);synchronized (this.beanFactoryMonitor) {
    this.beanFactory = beanFactory;}}catch (IOException ex) {
    throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);}
}

**loadBeanDefinitions()**方法为每个bean生成beanDefinition。

@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // 为给定的BeanFactory创建一个新的XmlBeanDefinitionReader。XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);// 使用此上下文配置bean定义阅读器// 资源加载环境。beanDefinitionReader.setEnvironment(getEnvironment());beanDefinitionReader.setResourceLoader(this);beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));//允许一个子类提供自定义的读取器初始化,//然后继续实际加载bean定义。initBeanDefinitionReader(beanDefinitionReader);loadBeanDefinitions(beanDefinitionReader);
}
  • prepareBeanFactory(beanFactory):配置标准的beanFactory,设置ClassLoader,设置SpEL表达式解析器,添加忽略注入的接口,添加bean,添加bean后置处理器等。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 告诉内部bean工厂使用上下文的类装入器等。beanFactory.setBeanClassLoader(getClassLoader());beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// 使用上下文回调配置bean工厂。beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));beanFactory.ignoreDependencyInterface(EnvironmentAware.class);beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);beanFactory.ignoreDependencyInterface(MessageSourceAware.class);beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);// BeanFactory接口没有注册为普通工厂中的可解析类型。// MessageSource作为一个bean注册(并找到自动装配)。beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);//将早期后处理器注册为applicationlistener来检测内部bean。beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));// Detect a LoadTimeWeaver and prepare for weaving, if found.if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
    beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));// Set a temporary ClassLoader for type matching.beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}// 注册默认的环境bean。if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
    beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());}if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
    beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());}if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
    beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());}
}
  • postProcessBeanFactory(beanFactory):所有的beanDefinition已经加载,但是还没有实例化。允许在子类中对beanFactory进行扩展处理。比如添加ware相关接口自动装配设置,添加后置处理器等,是子类扩展prepareBeanFactory(beanFactory)的方法。在应用上下文的内部bean factory初始化之后修改bean factory。所有的bean definitions已经被加载,但是还没有bean被实例化。在明确的ApplicationContext实现中允许指定BeanPostProcessors等的注册
// 注册request/session scopes等
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // ServletContextAwareProcessor中拿到应用上下文持有的servletContext引用和servletConfig引用// 添加ServletContextAwareProcessor处理器beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));// 在自动注入时忽略指定的依赖接口beanFactory.ignoreDependencyInterface(ServletContextAware.class);beanFactory.ignoreDependencyInterface(ServletConfigAware.class);// 注册web应用的scopesWebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);// 注册和环境有关的beansWebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
}
  • invokeBeanFactoryPostProcessors(beanFactory):实例化并调用所有注册的beanFactory后置处理器(实现接口BeanFactoryPostProcessor的bean,在beanFactory标准初始化之后执行)。

    执行了BeanDefinitionRegistryPostProcessor(此处只有ConfigurationClassPostProcessor)

    执行了BeanFactoryPostProcessor

    完成了@Configuration配置文件的解析,并且把扫描到的、配置的Bean定义信息都加载进容器里

BeanPostProcessor使用例子:实现BeanPostProcessor重写postProcessBeforeInitialization()在这个方法中可以对当前的Bean进行修改。最后拿到的bean是修改之后的Bean。

@Configuration
public class UserBean {
    private static final Logger logger = Logger.getLogger(String.valueOf(UserBean.class));@Bean(name = "myUser")public User getUser(){
    User user = new User();user.setAge(23);Date date = new Date();user.setDate(date);user.setName("张三");logger.info("=====> UserBean配置信息:"+ JSONObject.toJSONString(user));return user;}}@Component
public class UserBeanPostProcessor implements BeanPostProcessor {
    private static final Logger logger = Logger.getLogger(String.valueOf(UserBeanPostProcessor.class));@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    final String name = "myUser";if(name.equals(beanName)){
    User user = (User) bean;user.setName("李四");user.setDate(new Date());logger.info("=====> postProcessBeforeInitialization():"+ JSONObject.toJSONString(user));}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    return bean;}
}
  • registerBeanPostProcessors(beanFactory):实例化和注册beanFactory中扩展了BeanPostProcessor的bean。将 BeanPostProcessor 注册到 BeanFactory 中,并没有执行
// 获取容器中类型为BeanPostProcessor的bean的名城
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

BeanPostProcessor实现类有:Spring默认的三个
AutowiredAnnotationBeanPostProcessor(处理被@Autowired注解修饰的bean并注入)
RequiredAnnotationBeanPostProcessor(处理被@Required注解修饰的方法)
CommonAnnotationBeanPostProcessor(处理@PreDestroy@PostConstruct@Resource等多个注解的作用)等。

  • initMessageSource():初始化国际化工具类MessageSource
  • initApplicationEventMulticaster():初始化事件广播器
  • onRefresh():模板方法,在容器刷新的时候可以自定义逻辑,不同的Spring容器做不同的事情。
  • registerListeners():注册监听器,广播early application events
  • finishBeanFactoryInitialization(beanFactory):实例化所有剩余的(非懒加载)单例
    比如invokeBeanFactoryPostProcessors方法中根据各种注解解析出来的类,在这个时候都会被初始化。实例化的过程各种BeanPostProcessor开始起作用。
  • finishRefresh():refresh做完之后需要做的其他事情。清除上下文资源缓存(如扫描中的ASM元数据) 初始化上下文的生命周期处理器,并刷新(找出Spring容器中实现了Lifecycle接口的bean并执行start()方法)。发布ContextRefreshedEvent事件告知对应的ApplicationListener进行响应的操作。

SpringBean 创建

refresh()的finishBeanFactoryInitialization()开始

循环所有定义的bean,判断是不是工厂bean,如果是普通的bean,直接调用getBean(),getBean()中调用doGetBean()。doGetBean方法中获得Bean并且返回。

@Override
public void preInstantiateSingletons() throws BeansException {
    if (logger.isTraceEnabled()) {
    logger.trace("Pre-instantiating singletons in " + this);}//遍历副本以允许init方法注册新的bean定义。//虽然这可能不是常规工厂引导的一部分,但它在其他方面工作得很好。List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// 触发所有非惰性单例bean的初始化…for (String beanName : beanNames) {
    RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    if (isFactoryBean(beanName)) {
    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {
    final FactoryBean<?> factory = (FactoryBean<?>) bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
    isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());}else {
    isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {
    getBean(beanName);}}}else {
    getBean(beanName);}}}// Trigger post-initialization callback for all applicable beans...for (String beanName : beanNames) {
    Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {
    final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {
    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    smartSingleton.afterSingletonsInstantiated();return null;}, getAccessControlContext());}else {
    smartSingleton.afterSingletonsInstantiated();}}}
}

Object singletonInstance = getSingleton(beanName);从单例缓存池中获取。getBean()方法特别长,本质是获取一个javaBean,内部实现了Bean的创建。

。。。。。头都大了,好多都看不懂,有时间再看

  相关解决方案