BeanDefinition
我们知道 java 是面向对象的编程语言,但是在 Spring 当中除了对象还有一个特别重要的概念,那就是 bean,我们的交给 Spring 管理的对象最终都会由 Spring 将其变成 bean,那么对象、bean、BeanDefinition 是什么关系呢
Spring IoC容器管理一个或多个bean。这些bean是使用您提供给容器的配置元数据创建的(例如,以XML<bean/>
定义的形式 )。
在容器本身内,这些bean定义表示为BeanDefinition
对象,这些对象包含(除其他信息外)以下元数据:
- 包限定的类名:通常,定义了Bean的实际实现类。
- Bean行为配置元素,用于声明Bean在容器中的行为(作用域,生命周期回调等)。
- 引用其他bean来完成其工作所需要的。这些引用也称为协作者或依赖项。
- 要在新创建的对象中设置的其他配置设置-例如,池的大小限制或要在管理连接池的bean中使用的连接数。
此元数据转换为构成每个bean定义的一组属性。下表描述了这些属性:
Property
|
Explained in…
|
---|---|
Class | |
Name | |
Scope | |
Constructor arguments | |
Properties | |
Autowiring mode | |
Lazy initialization mode | |
Initialization method | |
Destruction method |
Bean元数据和手动提供的单例实例需要尽早注册,以便容器在自动装配和其他自省步骤期间正确地判断它们。
虽然在某种程度上支持覆盖现有元数据和现有的单例实例,但在运行时注册新bean(与对工厂的实时访问并发)不受官方支持,
可能会导致并发访问异常、bean容器中的不一致状态,或者两者都有。
Bean作用域 Scope
Scope | Description |
---|---|
(Default) Scopes a single bean definition to a single object instance for each Spring IoC container. | |
Scopes a single bean definition to any number of object instances. | |
Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring | |
Scopes a single bean definition to the lifecycle of an HTTP | |
Scopes a single bean definition to the lifecycle of a | |
Scopes a single bean definition to the lifecycle of a |
代码证明:
注解:
package com.davinqi.mytest.spring;
import java.lang.annotation.*;
/**
* @Author qixi....
* @Date 2021/4/22 2:19 下午
* @Version 1.0
**/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyBeanAnno {
String value() default "";
}
测试Bean 作用域的类。
package com.davinqi.mytest.spring;
import org.springframework.context.annotation.Scope;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import java.lang.ref.PhantomReference;
/**
* @Author qixi....
* @Date 2021/4/22 2:11 下午
* @Version 1.0
**/
@Component
public class MyBeanPostVo {
public MyBeanPostVo() {
System.out.println(">>>>>>>>> 我要new个对象");
}
@EventListener(classes = {ContextRefreshedEvent.class})
public void testEvent(ContextRefreshedEvent event){
System.out.println("====================== 容器完成刷新,可以工作了 done---->"+event.toString());
}
@MyBeanAnno(value = " 哎, 该回家了!")
private String nnnnn = " 欧耶,出去玩 !";
public void sayHi () {
System.out.println(">>>>>>>>> 我是 sayHi : " + nnnnn);
}
}
package com.davinqi.mytest.spring;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/**
* @Author qixi....
* @Date 2021/4/22 2:10 下午
* @Version 1.0
**/
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof MyBeanPostVo) {
System.out.println(">>>>>>>> 封装数据 ... ");
Field[] declaredFields = bean.getClass().getDeclaredFields();
for (Field field : declaredFields) {
MyBeanAnno annotation = field.getAnnotation(MyBeanAnno.class);
if (annotation != null) {
String value = annotation.value();
field.setAccessible(true);
try {
field.set(bean, value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
return bean;
}
}
@EventListener(classes = {ContextRefreshedEvent.class})
public void testEvent(ContextRefreshedEvent event){
System.out.println("====================== 容器完成刷新,可以工作了 done---->"+event.toString());
}
这块代码是用来监听Spring 容器启动后 调用refresh()后放容器中发布的一个完成的事件 我们使用注解声明这个事件后就可以监听是否刷新完成了。。。
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
protected void finishRefresh() {
this.clearResourceCaches();
this.initLifecycleProcessor();
this.getLifecycleProcessor().onRefresh();
this.publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this)));
LiveBeansView.registerApplicationContext(this);
}
2021-04-22 15:05:02.681 INFO 92914 --- [ main] com.davinqi.mytest.HelloBoyTest : Starting HelloBoyTest using Java 11.0.10 on QXQ.local with PID 92914 (started by qixiangqun in /Users/qixiangqun/mycode/mytest)
2021-04-22 15:05:02.683 INFO 92914 --- [ main] com.davinqi.mytest.HelloBoyTest : No active profile set, falling back to default profiles: default
>>>>>>>>> 我要new个对象
>>>>>>>> 封装数据 ...
====================== 容器完成刷新,可以工作了 done---->org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@666b83a4, started on Thu Apr 22 15:05:02 CST 2021]
2021-04-22 15:05:03.252 INFO 92914 --- [ main] com.davinqi.mytest.HelloBoyTest : Started HelloBoyTest in 0.989 seconds (JVM running for 2.319)
>>>>>>>> 使用 helloBoy ...
>>>>>>>>> 我是 sayHi : 哎, 该回家了!
@Component
public class MyBeanPostVo
可以知道 这个对象,默认的情况下是个单例的Bean 。通过日志可以知道,在容器刷新前,已经new好了 并且 Bean后置处理器已经重新赋值( 这块其实是:给BeanDefiniton 的 属性赋值)
现在改为:
@Component
@Scope("prototype")
public class MyBeanPostVo
2021-04-22 15:10:51.103 INFO 93089 --- [ main] com.davinqi.mytest.HelloBoyTest : No active profile set, falling back to default profiles: default
>>>>>>>>> 我要new个对象
>>>>>>>> 封装数据 ...
====================== 容器完成刷新,可以工作了 done---->org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@666b83a4, started on Thu Apr 22 15:10:51 CST 2021]
2021-04-22 15:10:51.755 INFO 93089 --- [ main] com.davinqi.mytest.HelloBoyTest : Started HelloBoyTest in 1.171 seconds (JVM running for 2.276)
>>>>>>>>> 我要new个对象
>>>>>>>> 封装数据 ...
>>>>>>>> 使用 helloBoy ...
>>>>>>>>> 我是 sayHi : 哎, 该回家了!
Disconnected from the target VM, address: '127.0.0.1:51129', transport: 'socket'
总结:
又上述代码中可知道
1,bean 的作用域默认为 单例 ,在容器其初始化时会 (refresh() )创建对象放入缓存集合中。 声明了prototype,后在每次使用时生成新的Bean。
2,@EventListener(classes = {ContextRefreshedEvent.class}) 注解声明监听器的方式的使用 ,在Spring中的观察者模式。
3,BeanPostProcessor 后置处理器接口可以对对象进行自定义的处理,以及在实际的应用。