当前位置: 首页 > article >正文

Spring底层源码(一)

Spring的入门代码:

public class XmlTest {

    public static void main(String[] args) {
        //构造一个容器.
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("springTest.xml");
        //从容器中获取Bean对象
        UserService userService = (UserService) context.getBean("userService");
        UserService a1 = (UserService) context.getBean("a1");
        UserService a2 = (UserService) context.getBean("a2");
        UserService a3 = (UserService) context.getBean("a3");
        //调用方法
        userService.test();
        a1.test();
        a2.test();
        a3.test();
    }
}

public class UserService {

    public void test() {
        System.out.println("我是一个bean");
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
	   https://www.springframework.org/schema/beans/spring-beans.xsd
	   http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"
>

    <bean id="a1" class="com.itbo.service.UserService"/>
    <bean id="a2" class="com.itbo.service.UserService"/>
    <bean id="a3" class="com.itbo.service.UserService"/>

    <bean id="userService" class="com.itbo.service.UserService" autowire="default">
    </bean>
</beans>

以上就是入门的Spring代码.

1:第一行代码,会构造一个ClassPathXmlApplicationContext对象,ClassPathXmlApplicationContext该如何理解,调用该构造方法除开会实例化得到一个对象

2: 会调用ClassPathXmlApplicationContext的getBean方法,会得到一个UserService对象,getBean()是如何实现的?返回的UserService对象和我们自己直接new的UserService对象有区别吗?

3:就是简单的调用UserService的test()方法.

但是用ClassPathXmlApplicationContext其实已经过时了,在新版的Spring MVC和Spring Boot的底层主要用的都是AnnotationConfigApplicationContext,比如:

public class AnnotationTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        UserService userService = (UserService) context.getBean("userService");
        userService.test();
    }
}
@ComponentScan("com.itbo")
public class AppConfig {

    @Bean
    public UserService userService() {
        return new UserService();
    }
}

目前,我们基本很少直接使用上面这种方式来用Spring,而是使用Spring MVC,或者Spring Boot,但是它们都是基于上面这种方式的,都需要在内部去创建一个ApplicationContext的,只不过:

  1. Spring MVC创建的是XmlWebApplicationContext,和ClassPathXmlApplicationContext类似,都是基于XML配置的
  2. Spring Boot创建的是AnnotationConfigApplicationContext.

因为AnnotationConfigApplicationContext是比较重要的,并且AnnotationConfigApplicationContext和ClassPathXmlApplicationContext大部分底层都是共同的.所以我们就分析AnnotationConfigApplicationContext的流程.

执行流程

然后进入到构造方法里面会看到如下图. 

那我们就挨个点着进去大概看一下.this方法如下.

 

 看着注释,很蒙圈,怎么就注册了那么多BeanPostProcessor,那就无脑点进去看看满足自己的好奇心.

都到这里了,心里还能控制住嘛.不得继续进去看看,有个啥东西嘛.

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {

		DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
		if (beanFactory != null) {

			// 设置beanFactory的OrderComparator,为AnnotationAwareOrderComparator
			// 它是一个Comparator,是一个比较器,可以用来进行排序,比如new ArrayList<>().sort(Comparator)
			if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
				beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
			}
			// 设置自动装配候选者解析式(判断某个bean是不是可以用来进行进行自动注入),用来解析某个bean能不能进行自动注入,bean的autowireCandidate的属性是否为true.
			if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
				beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
			}
		}

		Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

		// 注册ConfigurationClassPostProcessor类型的BeanDefinition
		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// 注册AutowiredAnnotationBeanPostProcessor类型的BeanDefinition
		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// 注册CommonAnnotationBeanPostProcessor类型的BeanDefinition
		// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
		if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// 注册PersistenceAnnotationBeanPostProcessor类型的BeanDefinition
		// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
		//@PersistenceUnit和@PersistenceContext注解的注入点的查找.类似于autowired和resource.
		if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition();
			try {
				def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
						AnnotationConfigUtils.class.getClassLoader()));
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(
						"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
			}
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// 注册EventListenerMethodProcessor类型的BeanDefinition
		if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
		}

		// 注册DefaultEventListenerFactory类型的BeanDefinition
		if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
		}

		return beanDefs;
	}

​这里是注册了一些最基本的PostProcesser,切记切记,一定要有个印象.(可以手动注册,也可以利用配置bean的方式,不懂,先记住.方便后面理解)

回过头来继续点进去注册过滤的那个类.

	public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
			Environment environment, @Nullable ResourceLoader resourceLoader) {

		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		this.registry = registry;

		// 添加includeFilters,Spring扫描的时候需要利用includeFilters,Spring扫描到某个类时如果能通过includeFilters的验证就证明这个类是一个Bean
		// 默认注册一个@Component注解对应的Filter
		if (useDefaultFilters) {
			registerDefaultFilters();
		}
		setEnvironment(environment);
		setResourceLoader(resourceLoader);
	}
 protected void registerDefaultFilters() {
        this.includeFilters.add(new AnnotationTypeFilter(Component.class));
        ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
        try {
            this.includeFilters.add(new AnnotationTypeFilter(
                    ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
            logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
        } catch (ClassNotFoundException ex) {
            // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
        }
        try {
            this.includeFilters.add(new AnnotationTypeFilter(
                    ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
            logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
        } catch (ClassNotFoundException ex) {
            // JSR-330 API not available - simply skip.
        }
    }

内部的实现就是这样的.可能初看不懂,没关系,记住,有个大概印象.源码就是反复看重复看的.

this方法看完了,退回到构造方法,继续看注册配置类的方法.

	private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
			@Nullable BeanDefinitionCustomizer[] customizers) {

		// 直接生成一个AnnotatedGenericBeanDefinition
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
		// 判断当前abd是否被标注了@Conditional注解,并判断是否符合所指定的条件,如果不符合,则跳过,不进行注册
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		// 设置supplier、scope属性,以及得到beanName
		abd.setInstanceSupplier(supplier);
		// @Scope注解的元数据信息
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

		// 获取Lazy、Primary、DependsOn、Role、Description注解信息并设置给abd
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

		if (qualifiers != null) {
			for (Class<? extends Annotation> qualifier : qualifiers) {
				if (Primary.class == qualifier) {
					abd.setPrimary(true);
				}
				else if (Lazy.class == qualifier) {
					abd.setLazyInit(true);
				}
				else {
					abd.addQualifier(new AutowireCandidateQualifier(qualifier));
				}
			}
		}
		// 使用自定义器修改BeanDefinition
		if (customizers != null) {
			for (BeanDefinitionCustomizer customizer : customizers) {
				customizer.customize(abd);
			}
		}

		// BeanDefinition中是没有beanName的,BeanDefinitionHolder中持有了BeanDefinition,beanName,alias
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

		// 解析Scope中的ProxyMode属性,默认为no,不生成代理对象
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

		// 注册到registry中
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

思路就是封装成一个BeanDefinition然后注册到BeanFactory中.

在回到构造方法进入到refresh方法中.

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			// 刷新BeanFactory,得到一个空的BeanFactory-Default
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();  // co

			// Prepare the bean factory for use in this context.
			// 准备BeanFactory
			// 1. 设置BeanFactory的类加载器、表达式解析器、类型转化注册器
			// 2. 添加三个BeanPostProcessor,注意是具体的BeanPostProcessor实例对象
			// 3. 记录ignoreDependencyInterface
			// 4. 记录ResolvableDependency
			// 5. 添加三个单例Bean
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				// 子类可以对BeanFactory进行进一步初始化
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				// BeanFactory准备好了之后,执行BeanFactoryPostProcessor,开始对BeanFactory进行处理
				// 默认情况下:
				// 此时beanFactory的beanDefinitionMap中有6个BeanDefinition,5个基础BeanDefinition+AppConfig的BeanDefinition
				// 而这6个中只有一个BeanFactoryPostProcessor:ConfigurationClassPostProcessor
				// 这里会执行ConfigurationClassPostProcessor进行@Component的扫描,扫描得到BeanDefinition,并注册到beanFactory中
				// 注意:扫描的过程中可能又会扫描出其他的BeanFactoryPostProcessor,那么这些BeanFactoryPostProcessor也得在这一步执行
				invokeBeanFactoryPostProcessors(beanFactory);  //BeanDefinitionRegistryPostProcessor ,BeanFactoryPostProcessors

				// Register bean processors that intercept bean creation.
				// 从BeanFactory找出扫描得到得BeanPostProcessor,实例化并注册到BeanFactory中
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				// 初始化MessageSource,如果配置了一个名字叫做“messageSource”的BeanDefinition
				// 就会把这个Bean创建出来,并赋值给ApplicationContext的messageSource属性
				// 这样ApplicationContext就可以使用国际化的功能了
				initMessageSource();

				// Initialize event multicaster for this context.
				// 设置ApplicationContext的applicationEventMulticaster
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				// 执行子类的onRefresh方法
				onRefresh();

				// Check for listener beans and register them.
				// 注册Listener
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				// 完成beanFactory的初始化(实例化非懒加载的单例bean)
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				// 发布事件
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

refresh方法是一个模板方法,不管哪个容器实现还是SpringBoot最终创建Bean都会走到这个里面. 可以说这个方法是重中之重.大家先大概有个印象.后面我还会陆续分享Bean的循环依赖了生命周期了事务等等.

生活最主要的还是感受,坚持是一种刻意的练习,不断寻找缺点突破缺点的过程,而不是重复做某件事情。

有什么理解不对的地方希望大家可以多多指教.

如果大家喜欢我的分享的话,可以关注下我的微信公众号

心有九月星辰


                

http://www.kler.cn/a/383765.html

相关文章:

  • 【LeetCode】【算法】283. 移动零
  • RPC核心实现原理
  • Rust常用数据结构教程 Map
  • 【JS学习】08. web API-事件进阶
  • CAS 详解
  • sql数据库-DQL-基本查询
  • 【Mac】PD报错:无法为“Windows” 完成操作,虚拟机ID无效的解决办法
  • 中科院二区idea:多尺度注意力+特征融合!把准11个创新套路,直通毕业!
  • 高级数据库 项目流程记录
  • Oracle 第21章:实时应用集群(RAC)
  • 梧桐数据库空间向量使用介绍分享
  • git的使用、router和route的区别以及v-show和v-if的差别
  • 基于Python+Vue开发的蛋糕商城管理系统
  • 定高虚拟列表:让大数据渲染变得轻松
  • 智慧城市的守护者——智能井盖监测终端
  • 微信小程序 uniapp网络记账设计个人理财系统
  • 【数据结构】B树
  • GBase与梧桐数据库窗口函数使用的比较
  • JMeter性能测试实现与分析分享
  • 【大数据学习 | kafka高级部分】kafka的文件存储原理
  • GPT-5 一年后发布?对此你有何期待?
  • 英语supremacist
  • SpringBoot、Spring、SpringMVC三者之间的关系与区别
  • xrc的比赛
  • mysql特性
  • uni生成海报并保存