Spring<3>Spring之底层架构核心设计解析

//1. 什么是bd 2. bd怎么定义
//2.scan 扫描器 可以扫描------>ScannedGenericBeanDefinition
//3.reader 读取器 可以读取------>AnnotatedGenericBeanDefinition
//4.MetadataReader
//5.beanFacoty和context的区别
//6.factorybean
//7.ExcludeFilter和IncludeFilter
之前我也说了Spring的大体流程,以及我也写了代码
Spring先根据构造方法构造出一个原生的类--------->@Autowired进行属性赋值---->初始化前---->初始化---->初始化后------>bean
如果初始化之后有aop的话 可能还会衍生出来一个代理对象
这节我们就说下Spring中的核心架构
beandefination  bean的定义,Spring中用来描述Bean的组件,比如说

在这里插入图片描述

Spring中有很多方式去定义bean,在Spring中通常会有几种方式定义bean
1.<bean>标签
2.@bean注解
3.@Component(@Service @Controller)
这些都叫做声明式bean  我们还可以编程式定义bean

在这里插入图片描述

我们可以通过beanDefinition 设置某一个bean的属性,比如说
beanDefinition.setScope("prototype"); // 设置作用域
beanDefinition.setInitMethodName("init"); // 设置初始化方法
beanDefinition.setLazyInit(true); // 设置懒加载
声明式和编程式的定义的bean都类似,通过<bean/>,@Bean,@Component等申明式方式所定义的Bean,最终都会被Spring解析为对应的BeanDefinition对象,并放入Spring容器中。
BeanDefinationReader  可以直接吧某个类转化为BeanDefination,并且会解析该类上的注解比如说@Lazy之类的
#比如说
    AnnotationConfigApplicationContext  context = new AnnotationConfigApplicationContext(AppConfig.class);
        AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(context);
        annotatedBeanDefinitionReader.register(User.class);
        System.out.println(context.getBean("user"));
        
有了这个BeanDefinationReader的话 我就可以吧一个类加载成为BeanDefination, 然后放到Spring容器中了
通过.
annotatedBeanDefinitionReader.register(User.class); 这个api, 吧一个类放入到构建成一个Srpingbean对象然后再放入容器中
 
ClassPathBeanDefinition Scanner 扫描器 他可以进行扫描 扫描一个路径,
对扫描的类进行解析 比如,扫描到的类上如果存在@Component注解,那么就会把这个类解析为一个BeanDefinition.然后放到spring容器中

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.refresh();

ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.scan("com.lvhao");

System.out.println(context.getBean("userService"));

在这里插入图片描述

beanDefination是一个接口 有几个实现类

GenericBeanDefinition,Spring中 一个普通的beanDefination的实现类
叫做 GenericBeanDefinition,
ScannedGenericBeanDefinition----->被扫描出来的beanDefination
AnnotatedGenericBeanDefinition--------> annotatedBeanDefinitionReader.register(通过reader.register()的类)
而他们都是我们的GenericBeanDefinition的子类

我们再来看下下beanFactory 以及 ApplicationContext
beanFactory是一个接口 支持有关bean获取的一些操作

在这里插入图片描述

也就是说 ApplicationContext  比beanFactory的功能更加强大一些
支持事件驱动,国际化等一些功能,以及一些环境变量的问题
MetadataReader、ClassMetadata、AnnotationMetadata


    // spring用来解析类  继而封装成bd???  用reader来读取class 构造读取器 然后
        //classMetadata基于reader拿到元数据
        SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();

        // 构造一个MetadataReader
        MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("com.lvhao.UserService");

        // 得到一个ClassMetadata,并获取了类名
        ClassMetadata classMetadata = metadataReader.getClassMetadata();

        System.out.println(classMetadata.getClassName());
        // 获取一个AnnotationMetadata,并获取类上的注解信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        for (String annotationType : annotationMetadata.getAnnotationTypes()) {
          System.out.println(annotationType);
        }

factorybean 本质是一个bean

# 我此时的orderService没有加@Component
@Component("LvHaoFactoryBean")
public class LvHaoFactoryBean implements FactoryBean {
    // 呢么 orderService 仍然也是一个Bean
    public Object getObject() throws Exception {
        return new OrderService();
    }

    public Class<?> getObjectType() {
        return OrderService.class;
    }
}

在这里插入图片描述

但是当我从Spring中获取的时候就会获取到 
实现  FactoryBean 的getObject中返回的类,
属于Spring的扩展点之一,通常是用来整合第三方框架用的,将第三方构建好的类通过该方式可以整合到spring容器中 比如说sqlsessionFactoryBean 
通过mybatis构建好的sqlsession,交给Spring管理

在这里插入图片描述

7.ExcludeFilter和IncludeFilter  
着2个filter主要是做扫描用的
# 我在扫描的时候 及时com.lvhao下有这个UserService并且加了@Component 我spring也不会吧他当作一个bean
@ComponentScan(value = "com.lvhao", excludeFilters =
          扫描排除
        {@ComponentScan.Filter(
                type = FilterType.ASSIGNABLE_TYPE,
                classes = UserService.class)})

@ComponentScan(value = "com.lvhao",
       #  我在扫描的时候 你加入这个类上没有加@Component 我也会认为你是一个bean
        includeFilters = {@ComponentScan.Filter(
                type = FilterType.ASSIGNABLE_TYPE,
                classes = UserService.class)})

在这里插入图片描述
csdn文章推荐受影响解决办法10个字10行

csdn文章推荐受影响解决办法10个字10行

csdn文章推荐受影响解决办法10个字10行

csdn文章推荐受影响解决办法10个字10行

csdn文章推荐受影响解决办法10个字10行

csdn文章推荐受影响解决办法10个字10行

csdn文章推荐受影响解决办法10个字10行

csdn文章推荐受影响解决办法10个字10行

csdn文章推荐受影响解决办法10个字10行

csdn文章推荐受影响解决办法10个字10行

我们知道Spring容器启动的时候会干2件事情
第一件事情就是扫描
第二件事情就是创建非懒加载的单例bean
在spring容器刚开始就会有这个scanner 

scanner.scan().. 完成扫描 我们现在先去看下他是怎么去扫描的 扫描结束后他是怎么去加载非懒加载的单例bean的

在这里插入图片描述

在这里插入图片描述

# 上述就是大概流程  我们看看他是怎么扫描 因为我的扫描器的主要功能就是吧扫描得到的bd放入到Spring容器中
扫描的逻辑就是解析com.lvhao 下面的class所有包含@Component的  我给放入到bdmap中

#扫描逻辑比如说我传入一个com.lvhao                                       
	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		
		for (String basePackage : basePackages) {
		#// 通过asm技术  在com.lvhao 下面找对应的bd 如果加了@Component 的话我认为他是一个bean
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			for (BeanDefinition candidate : candidates) {
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				#  设置属性 是否是单例原型
				candidate.setScope(scopeMetadata.getScopeName());
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					#设置基础值  给这些bean 赋值默认
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
				// 解析这些注解上面的属性 并且set到bd中
				#处理Lazy,Primary,DependsOn,Role,Description
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				# 检查check是否名字重复 名字重复我就报错
				if (checkCandidate(beanName, candidate)) {
				# 封装bdholder然后用registry 进行注册到
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
						AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					##this.beanDefinitionMap.put(beanName, beanDefinition);	 底层会调用这里吧当前这个bean放入到beanDefinationMap中
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}
当我们扫描完成之后,我们就会去将这些bd开始初始化 生成非懒加载的单例beans
这里就开始进行初始化创建bean
暂且理解为doscan----->preInstantiateSingletons() 也就是扫描完毕之后就开始初始化创建bean

	@Override
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		//遍历beanName
		for (String beanName : beanNames) {
			//(暂时忽略) Root做合并用的 xml中的<bean标签 有parent属性
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			// 这里就体现出来了 要创建非懒加载的单例bean 如果这个bean是单例的并且是非懒加载的
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
		/ 如果是一个实现了factoryBean
				if (isFactoryBean(beanName)) {
				// 创建该对象   创建完毕之后放入到 singletonObjects中
			.. key 为beanName value 为当前beanDefination
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						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 {
					// 如果是一个普通bean 我直接创建 创建完毕之后放入到单例池中
			.. key 为beanName value 为当前beanDefination
					getBean(beanName);
				}
			}
		}

///  在所有的单例bean都创建完毕之后
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			///  看是否实现了SmartInitializingSingleton  这个接口 spring的扩展点之一
			if (singletonInstance instanceof SmartInitializingSingleton) {
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}

在这里插入图片描述

一个类如果实现了factoryBean 在spring初始化的时候
会创建 以beanName 为该bean的名字,bd 放入到单例池中
当我们 Object LvHaoFactoryBean = context.getBean("&LvHaoFactoryBean");
如果前面带&  会返回 factoryBean
如果不带& 会执行创建bean的逻辑---------->factory的getObject()方法




版权声明:本文为weixin_43689953原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。