一BeanDefinition 构建
public class BeanDefinitionCreationDemo {
public static void main(String[] args) {
//1.通过BeanDefinitionBuilder
//beanDefinitionBuilderToBuild();
// 2. 通过 AbstractBeanDefinition 以及派生类
creatBeanDefintionByGenericBeanDefinition();
}
private static void creatBeanDefintionByGenericBeanDefinition() {
GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
// 设置 Bean 类型
genericBeanDefinition.setBeanClass(Person.class);
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("id",123);
propertyValues.add("name","zhansan");
genericBeanDefinition.setPropertyValues(propertyValues);
}
private static void beanDefinitionBuilderToBuild() {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Person.class);
// 通过属性设置
beanDefinitionBuilder.addPropertyValue("age",18);
beanDefinitionBuilder.addPropertyValue("name","zhansan");
BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
// BeanDefinition 并非 Bean 终态,可以自定义修改
//后序补充
beanDefinition.setDescription("没事意思" +
"" +
"");
System.out.println(beanDefinition);
}
}
二 命名SpringBean
2.1bean name 的生成
- BeanNameGenerator
Strategy interface for generating bean names for bean definitions.
- 实现类
DefaultBeanNameGenerator
当前类没有指定id 或者name时候自动生成id和name
AnnotationBeanNameGenerator
* {@link org.springframework.beans.factory.support.BeanNameGenerator}
* implementation for bean classes annotated with the
* {@link org.springframework.stereotype.Component @Component} annotation
* or with another annotation that is itself annotated with
* {@link org.springframework.stereotype.Component @Component} as a
* meta-annotation. For example, Spring's stereotype annotations (such as
* {@link org.springframework.stereotype.Repository @Repository}) are
* themselves annotated with
* {@link org.springframework.stereotype.Component @Component}.
三 别名的作用
四 如何注册BeanDefinition
4.1 BeanDefinition 注册
• XML 配置元信息
• <bean name=” ...” ... />
4.2 Java 注解配置元信息
• @Bean
• @Component
• @Import
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(Config.class);
context.refresh();
Map<String, Config> beansOfType = context.getBeansOfType(Config.class);
System.out.println("configBean"+beansOfType);
System.out.println("1.命名 Bean 的注册方式"+context.getBean("userr"));
context.close();
}
/*2. 通过@Compontent 方式*/
@Component
public static class Config{
/*一 @Bean的方式 注册Bean*/
@Bean(name = {"user","xiaozi"})
public Person person(){
return new Person(){{
setAge(999);
setName("sanfeng");
}};
}
}
4.3 Java API 配置元信息
• 命名方式: BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)
• 非命名方式:
BeanDefinitionReaderUtils#registerWithGeneratedName(AbstractBeanDefinition,BeanDe
finitionRegistry)
• 配置类方式: AnnotatedBeanDefinitionReader#register(Class...)
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.refresh();
// 通过 BeanDefinition 注册 API 实现
// 1.命名 Bean 的注册方式
registerUserBeanDefinition(context, "customerNameByAPI");
// 2. 非命名 Bean 的注册方法
registerUserBeanDefinition(context, "");
System.out.println("获取所有UserBean"+context.getBeansOfType(Person.class));
context.close();
}
/**
*
* @param registry
* @param beanName
*/
public static void registerUserBeanDefinition(BeanDefinitionRegistry registry,String beanName ){
BeanDefinitionBuilder beanDefinitionBuilder = genericBeanDefinition(Person.class);
beanDefinitionBuilder.addPropertyValue("id",2l).addPropertyValue("name","zhansan")
.addPropertyValue("age",18L);
// 判断如果 beanName 参数存在时
if (StringUtils.hasText(beanName)){
registry.registerBeanDefinition(beanName,beanDefinitionBuilder.getBeanDefinition());
//非命名 Bean 注册方法
}else {
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinitionBuilder.getBeanDefinition(),registry);
}
}
public static void registerUserBeanDefinition(BeanDefinitionRegistry registry) {
registerUserBeanDefinition(registry, null);
}
五 实例化Bean
Bean 实例化( Instantiation)
5.1 常规方式
• 通过构造器( 配置元信息: XML、 Java 注解和 Java API )
• 通过静态工厂方法( 配置元信息: XML 和 Java API )
• 通过 Bean 工厂方法( 配置元信息: XML和 Java API )
• 通过 FactoryBean( 配置元信息: XML、 Java 注解和 Java API )
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 静态工厂方法实例化 Bean -->
<bean id="user-by-static-method" class="domain.Person" factory-method="createUser"/>
<!-- Bean工厂方法方法实例化 Bean -->
<bean id="user-by-instance-method" factory-bean="userFactory" />
<bean id="userFactory" class="bean.factory.DefaultUserFactory"/>
<!--factoryBean 实例化方法-->
<bean id="user-by-factory-bean" class="bean.factory.UserFacotryBean"></bean>
</beans>
UserFactroy
public class UserFacotryBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
return Person.createUser();
}
@Override
public Class<?> getObjectType() {
return Person.class;
}
}
静态工程创建
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 如果是 实现factory-method="createUser"
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
略略略
5.2 特殊方式
5.2.1通过 ServiceLoaderFactoryBean( 配置元信息: XML、 Java 注解和 Java API )
关键类ServiceLoader ServiceLoaderFactoryBean
- serviceLoad 用法
public static void demoServiceLoader() {
ServiceLoader<UserFactory> serviceLoader = ServiceLoader.load(UserFactory.class, Thread.currentThread().getContextClassLoader());
displayServiceLoader(serviceLoader);
}
private static void displayServiceLoader(ServiceLoader<UserFactory> serviceLoader) {
Iterator<UserFactory> iterator = serviceLoader.iterator();
while (iterator.hasNext()) {
UserFactory userFactory = iterator.next();
System.out.println(userFactory.createUser());
}
}
2.Spring 管理Serviceloader
2.1. 定义/META-INF/special-bean-instantiation-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userFactoryServiceLoader" class="org.springframework.beans.factory.serviceloader.ServiceLoaderFactoryBean">
<property name="serviceType" value="bean.factory.UserFactory"></property>
</bean>
</beans>
2.2使用spring管理serviceLoad
private static void serviceLoadSrpingBean() {
ApplicationContext beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/special-bean-instantiation-context.xml");
ServiceLoader<UserFactory> serviceLoader = beanFactory.getBean("userFactoryServiceLoader", ServiceLoader.class);
displayServiceLoader(serviceLoader);
}
5.2.2通过 AutowireCapableBeanFactory#createBean(java.lang.Class, int, boolean)
• 通过 BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)
// autowireCapableBeanFactory 实例化Bean
private static void autowireCapableBeanFactory() {
ApplicationContext beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/special-bean-instantiation-context.xml");
AutowireCapableBeanFactory autowireCapableBeanFactory = beanFactory.getAutowireCapableBeanFactory();
UserFactory userFactory= autowireCapableBeanFactory.createBean(DefaultUserFactory.class);
System.out.println(userFactory.createUser());
}
六初始化SpringBean
Bean 初始化( Initialization)
6.1 @PostConstruct 标注方法
- PostConctrust 是java提供的注解
6.2 实现 InitializingBean 接口的 afterPropertiesSet() 方法
6.3 自定义初始化方法
• XML 配置: <bean init-method=” init” ... />
• Java 注解: @Bean(initMethod=” init” )
• Java API: AbstractBeanDefinition#setInitMethodName(String)
6.4 代码Demo
/**
* 默认 {@link UserFactory} 实现
* Create by dgx 2021/9/5 22:48
*/
public class DefaultUserFactory implements UserFactory, InitializingBean {
//1. 基于@PostConstruct 注解 java原生注解
@PostConstruct
public void init(){
System.out.println("使用@PostConstruct 初始化UserFactory");
}
//2. 通过自定义初始化化方法
public void initUserFactory(){
System.out.println("通过自动初始化化方法 初始化UserFactory");
}
// 3.实现 InitializingBean 注解
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("通过InitializingBean 初始化UserFactory");
}
/**
* 37 初始化Spring Bean
* Create by dgx 2021/10/7 15:37
*/
@Configuration
public class BeanInitializationDemo {
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注册 Configuration Class(配置类)
applicationContext.register(BeanInitializationDemo.class);
// 启动 Spring 应用上下文
applicationContext.refresh();
// 非延迟初始化在 Spring 应用上下文启动完成后,被初始化
System.out.println("Spring 应用上下文已启动...");
// 依赖查找 UserFactory
UserFactory userFactory = applicationContext.getBean(UserFactory.class);
System.out.println(userFactory);
System.out.println("Spring 应用上下文准备关闭...");
// 关闭 Spring 应用上下文
applicationContext.close();
System.out.println("Spring 应用上下文已关闭...");
}
// Bean定义自顶注解方法名称
@Bean(initMethod = "initUserFactory")
@Lazy(value = false)
public UserFactory userFactory() {
return new DefaultUserFactory();
}
}
6.4 源码执行时机
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
// 此处执行 @PostConstruct方法
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 此处执行 自定义的initMethod方法 和InitInitializingBean 接口方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
/**
* Give a bean a chance to react now all its properties are set,
* and a chance to know about its owning bean factory (this object).
* This means checking whether the bean implements InitializingBean or defines
* a custom init method, and invoking the necessary callback(s) if it does.
* @param beanName the bean name in the factory (for debugging purposes)
* @param bean the new bean instance we may need to initialize
* @param mbd the merged bean definition that the bean was created with
* (can also be {@code null}, if given an existing bean instance)
* @throws Throwable if thrown by init methods or by the invocation process
* @see #invokeCustomInitMethod
*/
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 实现了 InitializingBean
((InitializingBean) bean).afterPropertiesSet();
}
}
// 自定义了BeanDefinition
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
七 延迟初始化 和非延迟初始化的区别
区别是 延迟初始化化 是getBean的 适合处理初始化方法 非延迟初始化则是容器刷新完成之前