一前言
正如我们所熟悉的,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 BeanMetadataAttributeAccessorimplements BeanDefinition, Cloneable {//默认作用域名称的常量:等效于单例public static final String SCOPE_DEFAULT = "";//自动装配的一些常量// autowireMode = 0,默认值,未激活Autowiring。// bean 标签的 autowire 属性值为 no// 1、在xml中需要手动指定依赖注入对象 配置 property标签或者 constructor-arg标签// 2、使用 @Autowired 注解,autowireMode 的值也是 0public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;//autowireMode = 1,根据set方法的的名称作为Bean名称进行依赖查找//(去掉set,并尝试将首字母变为小写),并将对象设置到该set方法的参数上// bean 标签的 autowire 属性值配置为 byNamepublic static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;//autowireMode = 2,根据set方法参数的类型作为Bean类型进行依赖查找//并将对象设置到该set方法的参数上// bean 标签的 autowire 属性值配置为 byTypepublic static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;//autowireMode = 3,构造器注入// bean 标签的 autowire 属性值配置为 constructorpublic static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;//表明通过Bean的class的内部来自动装配 Spring3.0被弃用。// bean 标签的 autowire 属性值配置为 autodetect@Deprecatedpublic 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或是shutdownpublic static final String INFER_METHOD = "(inferred)";//Bean的class对象或是类的全限定名@Nullableprivate volatile Object beanClass;//默认的scope是单例,对应bean属性scope//@Scope@Nullableprivate String scope = SCOPE_DEFAULT;//是否是抽象,对应bean属性abstractprivate boolean abstractFlag = false;//是否懒加载,对应bean属性lazy-init,默认不是懒加载//@Lazy@Nullableprivate Boolean lazyInit;//自动注入模式,对应bean属性autowire,默认不进行自动装配private int autowireMode = AUTOWIRE_NO;//是否进行依赖检查,默认不进行依赖检查private int dependencyCheck = DEPENDENCY_CHECK_NONE;//用来表示一个bean的实例化是否依靠另一个bean的实例化,先加载dependsOn的bean,//对应bean属性depend-on//@DependsOn@Nullableprivate 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实例的方式之一@Nullableprivate Supplier <? > instanceSupplier;//是否允许访问非public方法和属性, 默认是trueprivate 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);}@Overridepublic void setParentName(String parentName) {this.parentName = parentName;}@Overridepublic String getParentName() {return this.parentName;}@Overridepublic AbstractBeanDefinition cloneBeanDefinition() {return new GenericBeanDefinition(this);}//其他代码省略}
通过代码分析,我们现在就可以创建一个spring可以使用的bean了:
public class SringApp {@Datastatic 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 的属性继承了 bean1context.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();// rootRootBeanDefinition definition = new RootBeanDefinition();definition.setBeanClass(Bean.class);definition.getPropertyValues().add("name", "xiaoli");definition.getPropertyValues().add("age", 1);context.registerBeanDefinition("bean1", definition);// childChildBeanDefinition 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() 其实是一个 GenericBeanDefinitioncontext.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());}@TTclass Person{}@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface TT{}}
输出:
[Test$TT]
4.2、ScannedGenericBeanDefinition
ScannedGenericBeanDefinition是AnnotatedBeanDefinition的另一个实现,与AnnotatedGenericBeanDefinition不同的是,ScannedGenericBeanDefinition是通过扫描 class,然后操作 asm进行解析的。
除此之外,其他是一样的。以后我们再来讨论关于asm相关的知识。

