一前言
正如我们所熟悉的,spring 是一个“大型的工厂”,在这个工厂中会产生一个个的实例,这些实例可以是单例的、非单例的。
工厂中的实例,也就是这次我们要进行分析的对象,BeanDefinition。
可以认为Spring中管理的所有对象,这些对象都是BeanDefinition.
二、类图分析
我们先看一下类图:
我们重点关注一下BeanDefinition,它是一个接口,并且继承了BeanMetadataElement,AttributeAccessor.
先分析一下这个类的关系
2.1、BeanMetadataElement
public interface BeanMetadataElement {
Object getSource();//返回对象的元数据
}
2.2、AttributeAccessor
public interface AttributeAccessor {
void setAttribute(String name, Object value);
Object getAttribute(String name);
Object removeAttribute(String name);
boolean hasAttribute(String name);
String[] attributeNames();
}
根据方法的命名,我们可以看出,这些方法都是对对象实例的操作。
2.3、BeanDefinition
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
//代码 不粘了
}
看一下类的结构图:
这个类,主要提供了一些对象的读取信息,和一些基本的设置信息。(比如类是不是单例啊、)
总结一下,BeanMetadataElement提供对象元数据,AttributeAccessor只对对象的属性进行读取和设置,BeanDefinition拥有了这两个接口的功能以外,还有读取类的基本信息的功能。
它完成了BeanDefinition的大部分工作,当然它也预留了一些我们必须要重写的方法:
需要子类实现的方法
- cloneBeanDefinition(): 克隆方法
- getParentName():获取当前Bean的父类
- setParentName():设置当前Bean的父类
三、抽象实现:AbstractBeanDefinition
再来看AbstractBeanDefinition
这个类,从名字中可以看出,它是一个模板抽象类。BeanDefinition
中只是定义了一系列的 get/set
方法,并没有提供对应的属性,在 AbstractBeanDefinition 中将所有的属性定义出来了。该抽象类下有个三个子类:GenericBeanDefinition、RootBeanDefinition、ChildBeanDefinition
。我们先来看AbstractBeanDefinition
本身的一些方法与属性。
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
//默认作用域名称的常量:等效于单例
public static final String SCOPE_DEFAULT = "";
//自动装配的一些常量
// autowireMode = 0,默认值,未激活Autowiring。
// bean 标签的 autowire 属性值为 no
// 1、在xml中需要手动指定依赖注入对象 配置 property标签或者 constructor-arg标签
// 2、使用 @Autowired 注解,autowireMode 的值也是 0
public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
//autowireMode = 1,根据set方法的的名称作为Bean名称进行依赖查找
//(去掉set,并尝试将首字母变为小写),并将对象设置到该set方法的参数上
// bean 标签的 autowire 属性值配置为 byName
public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
//autowireMode = 2,根据set方法参数的类型作为Bean类型进行依赖查找
//并将对象设置到该set方法的参数上
// bean 标签的 autowire 属性值配置为 byType
public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
//autowireMode = 3,构造器注入
// bean 标签的 autowire 属性值配置为 constructor
public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
//表明通过Bean的class的内部来自动装配 Spring3.0被弃用。
// bean 标签的 autowire 属性值配置为 autodetect
@Deprecated
public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
//检查依赖是否合法,在本类中,默认不进行依赖检查
//不进行检查
public static final int DEPENDENCY_CHECK_NONE = 0;
//对对象引用进行依赖性检查
public static final int DEPENDENCY_CHECK_OBJECTS = 1;
//对“简单”属性进行依赖性检查
public static final int DEPENDENCY_CHECK_SIMPLE = 2;
//对所有属性进行依赖检查
public static final int DEPENDENCY_CHECK_ALL = 3;
//若Bean未指定销毁方法,容器应该尝试推断Bean的销毁方法的名字,
//目前,推断的销毁方法的名字一般为close或是shutdown
public static final String INFER_METHOD = "(inferred)";
//Bean的class对象或是类的全限定名
@Nullable
private volatile Object beanClass;
//默认的scope是单例,对应bean属性scope
//@Scope
@Nullable
private String scope = SCOPE_DEFAULT;
//是否是抽象,对应bean属性abstract
private boolean abstractFlag = false;
//是否懒加载,对应bean属性lazy-init,默认不是懒加载
//@Lazy
@Nullable
private Boolean lazyInit;
//自动注入模式,对应bean属性autowire,默认不进行自动装配
private int autowireMode = AUTOWIRE_NO;
//是否进行依赖检查,默认不进行依赖检查
private int dependencyCheck = DEPENDENCY_CHECK_NONE;
//用来表示一个bean的实例化是否依靠另一个bean的实例化,先加载dependsOn的bean,
//对应bean属性depend-on
//@DependsOn
@Nullable
private String[] dependsOn;
/**
* autowire-candidate属性设置为false,这样容器在查找自动装配对象时,
* 将不考虑该bean,即它不会被考虑作为其他bean自动装配的候选者,
* 但是该bean本身还是可以使用自动装配来注入其他bean的
*/
private boolean autowireCandidate = true;
/**
* 自动装配时出现多个bean候选者时,将作为首选者,对应bean属性primary,默认不是首选的
* @Primary
*/
private boolean primary = false;
/**
* 用于记录Qualifier,对应子元素qualifier <bean><qualifier></qualifier></bean>
* 如果容器中有多个相同类型的 bean,这时我们就可以使用qualifier属性来设置加载指定Bean名称的bean
* @Qualifier
*/
private final Map < String, AutowireCandidateQualifier > qualifiers = new LinkedHashMap <>();
//java8的函数式接口,创建bean实例的方式之一
@Nullable
private Supplier <? > instanceSupplier;
//是否允许访问非public方法和属性, 默认是true
private boolean nonPublicAccessAllowed = true;
}
3.1、GenericBeanDefinition
GenericBeanDefinition
是spring2.5之后才有的,这个的想法是用来替代RootBeanDefinition/ChildBeanDefinition
,而RootBeanDefinition/ChildBeanDefinition
可以在spring
预加载的时候使用。
那我们主要关注一下GenericBeanDefinition这个类。
public class GenericBeanDefinition extends AbstractBeanDefinition {
private String parentName;
/**
* 创建GenericBeanDefinition之后,可以通过一下方法对bean的属性进行配置
*/
public GenericBeanDefinition() {
super();
}
public GenericBeanDefinition(BeanDefinition original) {
super(original);
}
@Override
public void setParentName(String parentName) {
this.parentName = parentName;
}
@Override
public String getParentName() {
return this.parentName;
}
@Override
public AbstractBeanDefinition cloneBeanDefinition() {
return new GenericBeanDefinition(this);
}
//其他代码省略
}
通过代码分析,我们现在就可以创建一个spring可以使用的bean了:
public class SringApp {
@Data
static class Bean {
String name;
int age;
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
GenericBeanDefinition definition = new GenericBeanDefinition();
definition.setBeanClass(Bean.class);
definition.getPropertyValues().add("name", "xiaoli");
definition.getPropertyValues().add("age", 1);
// 注册.
context.registerBeanDefinition("bean1", definition);
context.refresh();
Bean bean = (Bean) context.getBean("bean1");
System.out.println(bean);
}
}
GenericBeanDefinition其实还可以继承的
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
GenericBeanDefinition definition = new GenericBeanDefinition();
definition.setBeanClass(Bean.class);
definition.getPropertyValues().add("name", "xiaoli");
definition.getPropertyValues().add("age", 1);
context.registerBeanDefinition("bean1", definition);
GenericBeanDefinition definition2 = new GenericBeanDefinition();
definition2.setParentName("bean1");
// bean2 的属性继承了 bean1
context.registerBeanDefinition("bean2", definition2);
context.refresh();
Bean bean1 = (Bean) context.getBean("bean1");
Bean bean2 = (Bean) context.getBean("bean2");
// 虽然是这样,但是返回的false. 因为只是继承了属性.
System.out.println(bean1==bean2);
}
3.2、RootBeanDefinition 和 ChildBeanDefinition
RootBeanDefinition 这是一个最常用的实现类,Spirng 去创建 Bean 时是基于RootBeanDefinition去创建的!
RootBeanDefinition
继承了AbstractBeanDefinition
,在AbstractBeanDefinition
的基础上扩展了一些之外的功能,并且RootBeanDefinition
是没有父BeanDefinition
的。
RootBeanDefinition 和 ChildBeanDefinition这俩成双成对的。root节点不能有父类 , 其中儿子节点, 必须有父类 . 用法上和上面那个没啥区别.
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// root
RootBeanDefinition definition = new RootBeanDefinition();
definition.setBeanClass(Bean.class);
definition.getPropertyValues().add("name", "xiaoli");
definition.getPropertyValues().add("age", 1);
context.registerBeanDefinition("bean1", definition);
// child
ChildBeanDefinition definition2 = new ChildBeanDefinition("bean1");
context.registerBeanDefinition("bean2", definition2);
// 刷新
context.refresh();
Bean bean1 = (Bean) context.getBean("bean1");
Bean bean2 = (Bean) context.getBean("bean2");
System.out.println(bean1==bean2);
}
3.3、BeanDefinitionBuilder 工具
很显然就是一个Builder的工具类.
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(Bean.class);
// lazy 的意思是. 你需要(调用get("beanname")方法)的时候才要实例化.
builder.setLazyInit(true);
// builder.getBeanDefinition() 其实是一个 GenericBeanDefinition
context.registerBeanDefinition("bean3", builder.getBeanDefinition());
四、AnnotatedBeanDefinition
public interface AnnotatedBeanDefinition extends BeanDefinition {
AnnotationMetadata getMetadata();
MethodMetadata getFactoryMethodMetadata();
}
BeanDefinition的另一个扩展,就是枚举相关的AnnotatedBeanDefinition。当然这个扩展是从spring 2.5之后才有的。
4.1、子接口:AnnotatedGenericBeanDefinition
AnnotatedGenericBeanDefinition
是AnnotatedBeanDefinition
的一个具体实现。传入指定类后,可以获取类中的注解:
public class Test {
public static void main(String[] args) throws Exception {
AnnotatedGenericBeanDefinition genericBeanDefinition = new AnnotatedGenericBeanDefinition(Person.class);
genericBeanDefinition.setBeanClassName("springBean");
genericBeanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);
genericBeanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
// genericBeanDefinition.setPropertyValues();给属性添加值
System.out.println(genericBeanDefinition.getMetadata().getAnnotationTypes());
}
@TT
class Person{
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TT{
}
}
输出:
[Test$TT]
4.2、ScannedGenericBeanDefinition
ScannedGenericBeanDefinition是AnnotatedBeanDefinition的另一个实现,与AnnotatedGenericBeanDefinition不同的是,ScannedGenericBeanDefinition是通过扫描 class,然后操作 asm进行解析的。
除此之外,其他是一样的。以后我们再来讨论关于asm相关的知识。