void setLazyInit(boolean lazyInit);
boolean isLazyInit();
void setDependsOn(@Nullable String… dependsOn);
@Nullable
String[] getDependsOn();
void setAutowireCandidate(boolean autowireCandidate);
boolean isAutowireCandidate();
void setPrimary(boolean primary);
boolean isPrimary();
void setFactoryBeanName(@Nullable String factoryBeanName);
@Nullable
String getFactoryBeanName();
void setFactoryMethodName(@Nullable String factoryMethodName);
@Nullable
String getFactoryMethodName();
ConstructorArgumentValues getConstructorArgumentValues();
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
MutablePropertyValues getPropertyValues();
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
void setInitMethodName(@Nullable String initMethodName);
@Nullable
String getInitMethodName();
void setDestroyMethodName(@Nullable String destroyMethodName);
@Nullable
String getDestroyMethodName();
void setRole(int role);
int getRole();
void setDescription(@Nullable String description);
@Nullable
String getDescription();
ResolvableType getResolvableType();
boolean isSingleton();
boolean isPrototype();
boolean isAbstract();
@Nullable
String getResourceDescription();
@Nullable
BeanDefinition getOriginatingBeanDefinition();
}
BeanDefinition 中的方法虽然多,但是结合我们平时在 XML 中的配置,这些方法其实都很好理解:
-
首先一开始定义了两个变量用来描述 Bean 是不是单例的,后面的 setScope/getScope 方法可以用来修改/获取 scope 属性。
-
ROLE_xxx 用来描述一个 Bean 的角色,ROLE_APPLICATION 表示这个 Bean 是用户自己定义的 Bean;ROLE_SUPPORT 表示这个 Bean 是某些复杂配置的支撑部分;ROLE_INFRASTRUCTURE 表示这是一个 Spring 内部的 Bean,通过 setRole/getRole 可以修改。
-
setParentName/getParentName 用来配置 parent 的名称,这块可能有的小伙伴使用较少,这个对应着 XML 中的
<bean parent="">
配置。 -
setBeanClassName/getBeanClassName 这个就是配置 Bean 的 Class 全路径,对应 XML 中的
<bean class="">
配置。 -
setLazyInit/isLazyInit 配置/获取 Bean 是否懒加载,这个对应了 XML 中的
<bean lazy-init="">
配置。 -
setDependsOn/getDependsOn 配置/获取 Bean 的依赖对象,这个对应了 XML 中的
<bean depends-on="">
配置。 -
setAutowireCandidate/isAutowireCandidate 配置/获取 Bean 是否是自动装配,对应了 XML 中的
<bean autowire-candidate="">
配置。 -
setPrimary/isPrimary 配置/获取当前 Bean 是否为首选的 Bean,对应了 XML 中的
<bean primary="">
配置。 -
setFactoryBeanName/getFactoryBeanName 配置/获取 FactoryBean 的名字,对应了 XML 中的
<bean factory-bean="">
配置,factory-bean 松哥在之前的入门视频中讲过,小伙伴们可以参考这里:https://www.bilibili.com/video/BV1Wv41167TU。 -
setFactoryMethodName/getFactoryMethodName 和上一条成对出现的,对应了 XML 中的
<bean factory-method="">
配置,不再赘述。 -
getConstructorArgumentValues 返回该 Bean 构造方法的参数值。
-
hasConstructorArgumentValues 判断上一条是否是空对象。
-
getPropertyValues 这个是获取普通属性的集合。
-
hasPropertyValues 判断上一条是否为空对象。
-
setInitMethodName/setDestroyMethodName 配置 Bean 的初始化方法、销毁方法。
-
setDescription/getDescription 配置/返回 Bean 的描述。
-
isSingleton Bean 是否为单例。
-
isPrototype Bean 是否为原型。
-
isAbstract Bean 是否抽象。
-
getResourceDescription 返回定义 Bean 的资源描述。
-
getOriginatingBeanDefinition 如果当前 BeanDefinition 是一个代理对象,那么该方法可以用来返回原始的 BeanDefinition 。
这个就是 BeanDefinition 的定义以及它里边方法的含义。
上面只是 BeanDefinition 接口的定义,BeanDefinition 还拥有诸多实现类,我们也来大致了解下。
先来看一张继承关系图:
这么多实现类看着有点眼花缭乱,不过搞清楚了每一个接口和类的作用,再看就很容易了。
2.1 AbstractBeanDefinition
AbstractBeanDefinition 是一个抽象类,它根据 BeanDefinition 中定义的接口提供了相应的属性,并实现了 BeanDefinition 中定义的一部分方法。BeanDefinition 中原本只是定义了一系列的 get/set 方法,并没有提供对应的属性,在 AbstractBeanDefinition 中将所有的属性定义出来了。
后面其他的实现类也基本上都是在 AbstractBeanDefinition 的基础上完成的。
2.2 RootBeanDefinition
这是一个比较常用的实现类,对应了一般的元素标签。
2.3 ChildBeanDefinition
可以让子 BeanDefinition 定义拥有从父 BeanDefinition 那里继承配置的能力。
2.4 GenericBeanDefinition
GenericBeanDefinition 是从 Spring2.5 以后新加入的 BeanDefinition 实现类。GenericBeanDefinition 可以动态设置父 Bean,同时兼具 RootBeanDefinition 和 ChildBeanDefinition 的功能。
2.5 AnnotatedBeanDefinition
表示注解类型 BeanDefinition,拥有获取注解元数据和方法元数据的能力。
2.6 AnnotatedGenericBeanDefinition
使用了 @Configuration 注解标记配置类会解析为 AnnotatedGenericBeanDefinition。
理论讲了这么多,接下来我们通过几行代码来实践下,验证一下我们前面所说的对不对。
首先项目中添加 spring-context 依赖,如下:
org.springframework
spring-context
5.2.6.RELEASE
然后我们来创建一个 User 类,如下:
public class User {
private String username;
private String address;
@Override
public String toString() {
return “User{” +
“username='” + username + ‘’’ +
“, address='” + address + ‘’’ +
‘}’;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
接下来我们先来验证 RootBeanDefinition。我们自己纯手工定义一个 RootBeanDefinition,并且将之注册到 Spring 容器中去。
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add(“username”, “javaboy”);
pvs.add(“address”, “www.javaboy.org”);
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(User.class, null, pvs);
ctx.registerBeanDefinition(“user”,rootBeanDefinition);
ctx.refresh();
User bean = ctx.getBean(User.class);
System.out.println(bean);
MutablePropertyValues 是定义对象中的一个一个属性,构造 RootBeanDefinition 的时候,我们传入了类名称和属性集合,最终把 rootBeanDefinition 注册到容器中去。剩下的事情由容器完成,然后我们就可以从容器中获取到 User 对象了。
最终输出结果如下:
User{username=‘javaboy’, address=‘www.javaboy.org’}
看了这个例子,小伙伴们应该能够大致明白,我们在 XML 中定义的各种属性,就是先被解析到 BeanDefinition 中,然后再注册到 Spring 容器中去,最后拿到我们需要的 Bean。
ChildBeanDefinition 具有从父 Bean 继承数据的能力,我们来看下这个怎么用。
首先新建一个 Person 类,Person 类在 User 类的基础上增加一个 nickname 属性,这样 Person 就可以继承到 User 的 username 和 address 两个属性的值了:
public class Person {
private String username;
private String address;
private String nickname;
@Override
public String toString() {
return “Person{” +
“username='” + username + ‘’’ +
“, address='” + address + ‘’’ +
“, nickname='” + nickname + ‘’’ +
‘}’;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
}
接下来自定义 ChildBeanDefinition:
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add(“username”, “javaboy”);
最后
我还通过一些渠道整理了一些大厂真实面试主要有:蚂蚁金服、拼多多、阿里云、百度、唯品会、携程、丰巢科技、乐信、软通动力、OPPO、银盛支付、中国平安等初,中级,高级Java面试题集合,附带超详细答案,希望能帮助到大家。
还有专门针对JVM、SPringBoot、SpringCloud、数据库、Linux、缓存、消息中间件、源码等相关面试题。
加入社区:https://bbs.youkuaiyun.com/forums/4304bb5a486d4c3ab8389e65ecb71ac0
notationConfigApplicationContext();
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add(“username”, “javaboy”);
最后
我还通过一些渠道整理了一些大厂真实面试主要有:蚂蚁金服、拼多多、阿里云、百度、唯品会、携程、丰巢科技、乐信、软通动力、OPPO、银盛支付、中国平安等初,中级,高级Java面试题集合,附带超详细答案,希望能帮助到大家。
[外链图片转存中…(img-MnQmbh3q-1725732453046)]
还有专门针对JVM、SPringBoot、SpringCloud、数据库、Linux、缓存、消息中间件、源码等相关面试题。
[外链图片转存中…(img-B9rw1Ev1-1725732453047)]
加入社区:https://bbs.youkuaiyun.com/forums/4304bb5a486d4c3ab8389e65ecb71ac0