深入了解Spring
Bean
Java bean和spring bean区别
- Java bean的属性私有,只能通过get和set方法来对属性进行操作。
- Spring bean是由spring容器生成和管理的对象。
spring Bean的定义方式
-
xml文件 。 声明式。
-
@bean注解。 声明式。
-
@component注解。声明式。
-
@BeanDefinition。编程式
-
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(); AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition(); beanDefinition.setBeanClass(User.class); annotationConfigApplicationContext.registerBeanDefinition("user",beanDefinition); annotationConfigApplicationContext.refresh(); //取出 User user=annotationConfigApplicationContext.getBean("user",User.class);
-
-
实现FactoryBean接口
-
自定义工厂类
public class ZhuFactoryBean implements FactoryBean { //获取对象 public Object getObject() throws Exception { Person person=new Person(); return person; } //获取类型 public Class<?> getObjectType() { return Person.class; } public boolean isSingleton() { return false; } }
-
定义bean和取出bean
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(); AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition(); beanDefinition.setBeanClass(ZhuFactoryBean.class); //注册工厂类会将工厂类本身添加进入容器,也会将工厂添加的bean注入容器 annotationConfigApplicationContext.registerBeanDefinition("person",beanDefinition); annotationConfigApplicationContext.refresh(); //取出工厂类 ZhuFactoryBean zhuFactoryBean=annotationConfigApplicationContext.getBean("&person",ZhuFactoryBean.class); //取出工厂定义的bean Person person=annotationConfigApplicationContext.getBean("person",Person.class); System.out.println(zhuFactoryBean); System.out.println(person);
-
-
使用supplier定义bean
-
annotationConfigApplicationContext.registerBean(User.class, new Supplier<User>() { @Override public User get() { User user=new User(); user.setAge(11); return user; } });
-
spring容器
单例池
- spring中单例池存放的是单例bean,内部数据结构为concurrentHashMap,spring源码中的定义为Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256)。map的key为name,value为bean对象。它用于保存非懒加载的单例Bean。如果对象使用了AOP完成了一些操作,那么放入单例池的就是代理对象而不是他本身。
Bean生命周期
思维导图
- 简单来说:
流程总结
通过BeanDefinitionReader接口将xml或者注解配置的对象转换成BeanFactory中的beanDefinitionMap中的beanDefination。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ldqJlZOb-1685347461590)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210718114056465.png)]**—>之后beanFactoryPostProcessor接口的postprocessorFactoryBean方法可以获取到对factoryBean的信息,也就能对beanDefination进行一些操作,例如对xml文件中的占位符进行拼接、对注解的扫描(例如@component修饰的类转化为一个beanDefinition对象)。----->**创建对象,过程可以分为下图两步。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YsWWdlRu-1685347461591)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210717191046208.png)]
spring在实例化的时候是采用反射的方式实例化对象的,之后填充属性。**---->**调用Aware接口中的方法(Aware接口可以帮助自定义对象获取容器类对象(ApplicationContext、BeanFactory等),如简单对象通过实现ApplicationContextAware接口,可以让这个对象get到ApplicationContext容器)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1eZvWHet-1685347461592)(C:\Users\Ric\AppData\Local\Temp\企业微信截图_16265793448073.png)]
**---->**在bean创建之前调用before方法,[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PYejt2Df-1685347461592)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210718112814382.png)]之后调用init方法,之后调用after方法(通过beanPostProcessor接口实现AOP,接口的实现类会创建代理对象)。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G87HYqDS-1685347461593)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210718112925284.png)]
**----》**之后就是一个完整的bean对象了。
思维导图:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hLy6FkuI-1685347461593)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210718114858308.png)]
debug spring源码
debug入口
源码地址:https://gitee.com/qurywu/spring_study.git
使用注解的方式创建bean对象,以及取出bean
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
User user = annotationConfigApplicationContext.getBean(User.class);
user.run();
初始化IOC
创建AnnotationConfigApplicationContext对象和核心方法
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
//step1
this();
//step2
this.register(componentClasses);
//step3
this.refresh();
}
step1:this()
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
this.beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
this.scopeMetadataResolver = new AnnotationScopeMetadataResolver();
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, (ResourceLoader)null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
这段代码是一个构造函数,用于创建一个AnnotatedBeanDefinitionReader对象。AnnotatedBeanDefinitionReader是一个用于读取注解的BeanDefinition的类,它的作用是将注解转换为BeanDefinition对象并注册到BeanDefinitionRegistry中。
在构造函数中,首先设置了beanNameGenerator和scopeMetadataResolver的值,分别用于生成Bean的名称和解析Bean的作用域。然后通过断言确保传入的BeanDefinitionRegistry和Environment对象不为空,接着将它们赋值给成员变量registry和conditionEvaluator。
最后,调用AnnotationConfigUtils.registerAnnotationConfigProcessors方法,该方法会注册一些用于处理注解的BeanPostProcessor,例如AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor等。
step2:this.register(componentClasses)
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
//如果传入了qualifiers参数,则遍历qualifiers数组,根据不同的限定符设置BeanDefinition的Primary、LazyInit或Qualifier属性。
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
int var10;
int var11;
if (qualifiers != null) {
Class[] var9 = qualifiers;
var10 = qualifiers.length;
for(var11 = 0; var11 < var10; ++var11) {
Class<? extends Annotation> qualifier = var9[var11];
if (Primary.class == qualifier) {
abd.setPrimary(true);
} else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
} else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
BeanDefinitionCustomizer[] var13 = customizers;
var10 = customizers.length;
for(var11 = 0; var11 < var10; ++var11) {
BeanDefinitionCustomizer customizer = var13[var11];
customizer.customize(abd);
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
这段代码是一个私有方法,用于注册一个BeanDefinition。该方法接收一个beanClass参数,表示要注册的Bean的类型;一个name参数,表示Bean的名称;一个qualifiers参数,表示Bean的限定符;一个supplier参数,表示Bean的实例提供者;一个customizers参数,表示BeanDefinition的自定义器。
在方法中,首先创建一个AnnotatedGenericBeanDefinition对象,并通过conditionEvaluator判断是否应该跳过该BeanDefinition。然后设置BeanDefinition的实例提供者和作用域,并根据传入的name或使用beanNameGenerator生成Bean的名称。接着调用AnnotationConfigUtils.processCommonDefinitionAnnotations方法处理BeanDefinition上的常见注解。
如果传入了qualifiers参数,则遍历qualifiers数组,根据不同的限定符设置BeanDefinition的Primary、LazyInit或Qualifier属性。如果传入了customizers参数,则遍历customizers数组,调用每个BeanDefinitionCustomizer的customize方法对BeanDefinition进行自定义。
最后,将BeanDefinition封装为BeanDefinitionHolder对象,并根据作用域设置代理模式,最终通过BeanDefinitionReaderUtils.registerBeanDefinition方法将BeanDefinition注册到BeanDefinitionRegistry中。
register的实质是注册到BeanDefinitionMap中
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
//beanDefinition校验
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var8) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var8);
}
}
//通过那么从beanDefinitionMap中拿到BeanDefinition
BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
//判断BeanDefinitionRegistry中是否已经存在同名的BeanDefinition对象。如果存在,则根据isAllowBeanDefinitionOverriding方法的返回值决定是否允许覆盖原有的BeanDefinition对象。如果允许覆盖,则根据BeanDefinition对象的角色和内容进行判断,如果需要覆盖则进行覆盖操作,否则不进行任何操作。
if (existingDefinition != null) {
if (!this.isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
if (existingDefinition.getRole() < beanDefinition.getRole()) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
} else if (!beanDefinition.equals(existingDefinition)) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
} else if (this.logger.isTraceEnabled()) {
this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
//如果不存在同名的BeanDefinition对象,则将BeanDefinition对象添加到BeanDefinitionRegistry中,并更新BeanDefinitionRegistry中的Bean名称列表。如果BeanDefinitionRegistry已经开始创建Bean,则需要进行同步操作
if (this.hasBeanCreationStarted()) {
synchronized