1 前言(个人理解)
1 spring的思想总是先收集数据(成员变量或者方法)封装好,后面在某个地方去使用
2 任何类都会变成beandefinition,这是类的初始化,就像从java文件到class文件必须要编译器,再到class对象必须要类加载器一样,再变成bean,就必须先变成bd,里面是类的定义,实例化只有一个入口那就是getBean(),这样类的生命周期就很清晰明了
3 beanpostProcesser 是一种扩展点思想,在bean的初始化(beanFactoryPostProesser)到实例化 伴随着各种beanPostProdcessor通过接口实现扩展和插拔
我们学习spring就是学习思想放到平时工作中,猜的意思就是我们来设计怎么设计
猜@Bean怎么实现(结论1)
我们一般在一个类中自定义创建一个第三方类,在上面打一个注解
@Configuration
public class MyStarterConfig {
@Bean
public MyStarerBean myStarerBean(){
return new MyStarerBean();
}
}
就会注入一个这个你new的对象 但怎么做到的 我们猜下,前提是知道bd中是通过factory-method属性来实例化的
1 在扫描器扫描到MystarerConfig的时候,扫描到该注解看到是@bean注解,就好把这个注解的信息封装成一个元数据,再初始化为一个bd,然后将该bd的factory-name变成方法名,fatory-method变成该方法
2 在实例化这个bd的时候 就会调用到这个方法进行创建
源码验证:
ConfigurationClassParser
this.processImports(configClass, sourceClass, this.getImports(sourceClass), true);
importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
String[] var19 = resources;
int var21 = resources.length;
for(int var22 = 0; var22 < var21; ++var22) {
String resource = var19[var22];
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
Set<MethodMetadata> beanMethods = this.retrieveBeanMethodMetadata(sourceClass);
Iterator var17 = beanMethods.iterator();
的确是封装成了一个 MethodMetadata,先收集 再使用
同理我们可以猜@value,因为这个是打在成员变量上,跟@Resoure一样,那我们可以大胆推测也是在ioc之前通过一个beanPostprocessor像收集@Resource去收集这个注解,然后在ioc的时候去注入
2 猜mybatis和feign之类的实现类怎么注入spring(结论2)
前提是基于fatoryBean实现的
1 扫描到mybatis的mapper肯定要先把它变成一个bd,然后它的factoty-bean属性就是mybatisFatoryBean
2 实例化的时候 再调用它的getObject方法进行实例化
源码验证:
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
Iterator var3 = beanDefinitions.iterator();
while(var3.hasNext()) {
BeanDefinitionHolder holder = (BeanDefinitionHolder)var3.next();
GenericBeanDefinition definition = (GenericBeanDefinition)holder.getBeanDefinition();
if (this.logger.isDebugEnabled()) {
this.logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + definition.getBeanClassName() + "' mapperInterface");
}
definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName());
definition.setBeanClass(this.mapperFactoryBean.getClass());
package org.mybatis.spring.mapper;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Set;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.util.StringUtils;
public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner {
public T getObject() throws Exception {
return this.getSqlSession().getMapper(this.mapperInterface);
}
所以不管怎样 都要先变成bd 再实例化
3 bean创建中怎么选择构造器和收集属性和aop的实现(结论3)
在实例化的时候 怎么去创建和对属性注入
前提是知道aop基于beanPostProessor的后置方法
1 创建一个beanPostProcessor来进行推断构造器(多个构造器),才能进行反射创建,这里为啥要做成接口等以后再理解
2 创建一个beanPostProcessor来进行属性收集 方便进行属性注入,做成接口是不同注解对应不同实现类
3 我们可以在创建一个beanPostProessor专门做代理 在实例化之后或者之前 都可以对这个bean生成代理,因为生成代理不是创建bean的主流程 所以做成扩展点,在实例化的时候顺便有需求就代理下
源码验证
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
BeanDefinition definition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
AbstractAutoProxyCreator
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware