Bean的诞生(一)

当从spring容器中获取某单例对象时,若该对象还未实例化,则需要从BeanDefinition转变为一个实例化对象,在spring中,单例的实例化有这几个步骤:
1.初始化创建(可以是构造方法创建,也可以是某类的实例化工厂方法或者是静态工厂方法去创建,还有实现FactoryBean接口去创建对象的等等)
2.收集注解信息(在一个类中,需要收集的注解信息可以有.@Autowired,@Resource,@Value,@PostConstruct,@PreDestroy)
3.对某些属性的注入(@Autowired,@Resource,@Value等注解的信息注入)
4.对已经可用的实例进行拓展处理(某些Aware接口的属性填充,是否需要代理等)

Bean的初始化

bean的初始化是较为复杂的,其中的代码大体能知道什么意思,但是不知道是否是因为某些功能要兼容.有些判断使用,笔者一直没有弄明白,对于bean的初始化创建,笔者也就不去贴源码分析,只是写下自己的一些感悟

Bean的初始化在源码中有三种:
第一种是去检索BeanDefinition中的instanceSupplier属性,如果这个属性不为空,会调用这里面的方法去实例化
第二种是去检索BeanDefinition中的FactoryMethodName是否有值,如果有的话就会去调用这个FactoryMethodName,在这儿又要分为静态 方法和实例方法两种,静态方法直接使用类去执行方法,实例方法的话,会有一个实例对象,先从容器中寻找该对象(没有则实例化),反射调用该实例的该方法,生成Bean.如果方法中有其他入参,这些入参,也会根据类型去Spring容器中寻找,并且会被使用到
第三种是使用构造方法去构建的,这里又会区分
首先是看有没有在构造方法上加**@Autowired注解,对于加了这个注解的作为首先构造方法,如果有多个构造方法有
@Autowired还会报错,需要
@Autowired**的required值设置为false,则会根据入参的长度排序,选择一个构造方法(不知道为什么需要这样的操作…)
如果没有注解,则会去使用无参构造方法去创建,无无参构造方法则会报错
很重要的一点:所有的初始化,涉及的入参都会去spring容器中去拿

就这样一个bean就被创建了.但是这把并不是一个完整的类,他只是一个半成品,想要完整,他还需要一些路去走

Bean注解收集

bean的注解的收集,仅仅是收集的作用,不会有其他的操作,其收集的注解分为两个阵营,都是继承了MergedBeanDefinitionPostProcessor的类.它们分别是:
AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor
其中MergedBeanDefinitionPostProcessor是继承了BeanPostProcessor,他在初始化前已经实例化了,详细可参考这篇博客

	protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof MergedBeanDefinitionPostProcessor) {
				MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
				bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
			}
		}
	}

在源码中AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor早就和ConfigurationClassPostProcessor一起加入spring中了.并也被实例化了,
那么分别看下AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor的postProcessMergedBeanDefinition就能窥探到注解收集的一些奥秘了

AutowiredAnnotationBeanPostProcessor:主要负责@Autowired注解和@Value注解的收集
入口postProcessMergedBeanDefinition方法

	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}

收集注解方法findAutowiringMetadata

	private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
		// 获取缓存的key值
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		//从缓存中取
		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
		if (InjectionMetadata.needsRefresh(metadata, clazz)) {
			synchronized (this.injectionMetadataCache) {
				metadata = this.injectionMetadataCache.get(cacheKey);
				if (InjectionMetadata.needsRefresh(metadata, clazz)) {
					if (metadata != null) {
						metadata.clear(pvs);
					}
					//如果缓存中没有就去搜寻
					metadata = buildAutowiringMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}
	private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
		//在这里判断是否含有@Autowired注解和@Value注解,this.autowiredAnnotationTypes在该类初始化时赋值了
		if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
			return InjectionMetadata.EMPTY;
		}

		//.....省略,具体的收集步骤,收集的方法和类会有不同的InjectionMetadata对应
	}
	public AutowiredAnnotationBeanPostProcessor() {
		//初始化的时候对于@Autowired注解和@Value注解进行了设置
		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()));
			logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - simply skip.
		}
	}

CommonAnnotationBeanPostProcessor:主要负责@Resource@PostConstruct@PreDestroy注解的收集
入口postProcessMergedBeanDefinition

	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {		//父类方法,搜寻@PostConstruct@PreDestroy注解
		super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
		//搜寻@Resource注解
		InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}

CommonAnnotationBeanPostProcessor的父类是InitDestroyAnnotationBeanPostProcessor方法.

InitDestroyAnnotationBeanPostProcessor的搜寻步骤和前面大约一致
t

private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
		//@PostConstruct@PreDestroy注解在this.initAnnotationType, this.destroyAnnotationType中定义
		if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
			return this.emptyLifecycleMetadata;
		}
		//.....省略,具体的收集步骤,收集的方法会有不同的LifecycleMetadata对应
	}

在初始化CommonAnnotationBeanPostProcessor时给this.initAnnotationType, this.destroyAnnotationType设置了值

	public CommonAnnotationBeanPostProcessor() {
		setOrder(Ordered.LOWEST_PRECEDENCE - 3);
		setInitAnnotationType(PostConstruct.class);
		setDestroyAnnotationType(PreDestroy.class);
		ignoreResourceType("javax.xml.ws.WebServiceContext");
	}

同样的收集@Resource过程也是一样的
判断resourceAnnotationTypes的类型

private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
		if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
			return InjectionMetadata.EMPTY;
		}
		//.....省略,具体的收集步骤,收集的方法会有不同的InjectionMetadata对应 
	}

resourceAnnotationTypes在这里

private static final Set<Class<? extends Annotation>> resourceAnnotationTypes = new LinkedHashSet<>(4);

	static {
		webServiceRefClass = loadAnnotationType("javax.xml.ws.WebServiceRef");
		ejbClass = loadAnnotationType("javax.ejb.EJB");
		
		resourceAnnotationTypes.add(Resource.class);
		if (webServiceRefClass != null) {
			resourceAnnotationTypes.add(webServiceRefClass);
		}
		if (ejbClass != null) {
			resourceAnnotationTypes.add(ejbClass);
		}
	}

总结一下:这个注解的收集有一套规范的模式:
对注解先进行设置,无论是构造方法中还是静态代码块,之后对注解收集时先去缓存中查询,有缓存先走缓存,如果没有就会去具体的收集,在收集中会针对不同注解生成不同的Metadata,这些Metadata在后续的属性注入以及方法调用方面是有用处的

Bean属性注入

Bean的属性注入是对@Autowired,@Resource,@Value这三个注解进行属性的注入的,其依赖的还是AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor这两个类
看下他们的注入类
AutowiredAnnotationBeanPostProcessorpostProcessProperties

@Override
	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		//上面有findAutowiringMetadata方法
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {
			//注入
			metadata.inject(bean, beanName, pvs);
		}
		//.......
	public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
		Collection<InjectedElement> checkedElements = this.checkedElements;
		Collection<InjectedElement> elementsToIterate =
				(checkedElements != null ? checkedElements : this.injectedElements);
		if (!elementsToIterate.isEmpty()) {
			for (InjectedElement element : elementsToIterate) {
				if (logger.isTraceEnabled()) {
					logger.trace("Processing injected element of bean '" + beanName + "': " + element);
				}
				//具体元素的注入方法
				element.inject(target, beanName, pvs);
			}
		}
	}

其中AutowiredAnnotationBeanPostProcessorelement有两种AutowiredFieldElementAutowiredMethodElement
AutowiredFieldElementinject方法

@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			Field field = (Field) this.member;
			Object value;
			if (this.cached) {
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			}
			else {
				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
				desc.setContainingClass(bean.getClass());
				Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
				Assert.state(beanFactory != null, "No BeanFactory available");
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				try {
					//获取值的具体操作,这里面方法比较深,不去细细分析了,大致上是,先去看这个值是不是@Value注解的,是的话,先解析下格式,格
					//式不对,直接把字符串注入进去,对的话会获取容器的embeddedValueResolvers属性,获取解析的properties文件从里取值,
					//如果是@Autowired的话就直接从容器中拿Bean对象放进去
					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
				}
				catch (BeansException ex) {
					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
				}
				//这一段应该是缓存啥的
				synchronized (this) {
					if (!this.cached) {
						if (value != null || this.required) {
							this.cachedFieldValue = desc;
							registerDependentBeans(beanName, autowiredBeanNames);
							if (autowiredBeanNames.size() == 1) {
								String autowiredBeanName = autowiredBeanNames.iterator().next();
								if (beanFactory.containsBean(autowiredBeanName) &&
										beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
									this.cachedFieldValue = new ShortcutDependencyDescriptor(
											desc, autowiredBeanName, field.getType());
								}
							}
						}
						else {
							this.cachedFieldValue = null;
						}
						this.cached = true;
					}
				}
			}
			if (value != null) {
				ReflectionUtils.makeAccessible(field);
				//最后反射注入属性
				field.set(bean, value);
			}
		}
	}

AutowiredMethodElement则是跟**@Autowired加在set方法上面去注入的格式,个人感觉不重要.不贴源码了
CommonAnnotationBeanPostProcessor
postProcessProperties方法,大体流程与AutowiredAnnotationBeanPostProcessor差不多,唯一的不同是element**,AutowiredAnnotationBeanPostProcessor中的
elementInjectionMetadata
InjectionMetadatainject方法

	protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
				throws Throwable {

			if (this.isField) {
				Field field = (Field) this.member;
				ReflectionUtils.makeAccessible(field);
				//依旧是反射注入,getResourceToInject方法也是从容器中取值
				field.set(target, getResourceToInject(target, requestingBeanName));
			}
			else {
				if (checkPropertySkipping(pvs)) {
					return;
				}
				try {
					Method method = (Method) this.member;
					ReflectionUtils.makeAccessible(method);
					method.invoke(target, getResourceToInject(target, requestingBeanName));
				}
				catch (InvocationTargetException ex) {
					throw ex.getTargetException();
				}
			}
		}

Bean的初始化,收集注解和注入是一系列过程,任何的Bean都需要走这些流程,在BeanPostProcessor的某些特殊类的方法,如MergedBeanDefinitionPostProcessorpostProcessMergedBeanDefinition是收集注解的
InstantiationAwareBeanPostProcessorpostProcessProperties的属性注入
有了这两个法宝,为我们自己自定义注解去进行注入提供了可能,是Spring的拓展点,可以做一些操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值