抽象实现:AbstractBeanDefinition
AbstractBeanDefinition实现了BeanDefinition定义的一系列操作,定义了描述Bean画像的一系列属性,在AbstractBeanDefinition的基础上,Spring衍生出了一系列具有特殊用途的BeanDefinition。
实现代码非常的多:
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable { //=====================定义众多常量。这一些常量会直接影响到spring实例化Bean时的策略 // 个人觉得这些常量的定义不是必须的,在代码里判断即可。Spring定义这些常量的原因很简单,便于维护,让读代码的人知道每个值的意义(所以以后我们在书写代码时,也可以这么来搞) //默认的SCOPE,默认是单例 public static final String SCOPE_DEFAULT = ""; // 自动装配的一些常量 public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO; public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME; public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE; public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR; @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 //(即未指定Bean的销毁方法,但是内部定义了名为close或是shutdown的方法,则容器推断其为销毁方法) public static final String INFER_METHOD = "(inferred)"; //=====================属性:基本囊括了Bean实例化需要的所有信息 //Bean的class对象或是类的全限定名 @Nullable private volatile Object beanClass; //默认的scope是单例 @Nullable private String scope = SCOPE_DEFAULT; //默认不为抽象类 private boolean abstractFlag = false; //默认不进行自动装配 private boolean lazyInit = false; //默认不是懒加载 private int autowireMode = AUTOWIRE_NO; //默认不进行依赖检查 private int dependencyCheck = DEPENDENCY_CHECK_NONE; // @@DependsOn 默认没有 @Nullable private String[] dependsOn; // autowire-candidate属性设置为false,这样容器在查找自动装配对象时,将不考虑该bean, // 备注:并不影响本身注入其它的Bean private boolean autowireCandidate = true; // 默认不是首选的 private boolean primary = false; //用于记录Qualifier,对应子元素qualifier=======这个字段有必要解释一下 // 唯一向这个字段放值的方法为本类的:public void addQualifier(AutowireCandidateQualifier qualifier) copyQualifiersFrom这个不算,那属于拷贝 // 调用处:AnnotatedBeanDefinitionReader#doRegisterBean 但是Spring所有调用处,qualifiers字段传的都是null~~~~~~~~~尴尬 // 通过我多放跟踪发现,此处这个字段目前【永远】不会被赋值(除非我们手动调用对应方法为其赋值) 但是有可能我才疏学浅,若有知道的 请告知,非常非常感谢 我考虑到它可能是预留字段~~~~ // 我起初以为这样可以赋值: //@Qualifier("aaa") //@Service //public class HelloServiceImpl 没想到,也是不好使的,Bean定义里面也不会有值 // 因此对应的方法getQualifier和getQualifiers 目前应该基本上都返回null或者[] private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>(0); //我理解为通过这个函数的逻辑初始化Bean,而不是构造函数或是工厂方法(相当于自己去实例化,而不是交给Bean工厂) @Nullable private Supplier<?> instanceSupplier; //是否允许访问非public方法和属性,应用于构造函数、工厂方法、init、destroy方法的解析 默认是true,表示啥都可以访问 private boolean nonPublicAccessAllowed = true; // 是否以一种宽松的模式解析构造函数,默认为true(宽松和严格体现在类型匹配上) private boolean lenientConstructorResolution = true; //工厂类名(注意是String类型,不是Class类型) 对应bean属性factory-method @Nullable private String factoryBeanName; //工厂方法名(注意是String类型,不是Method类型) @Nullable private String factoryMethodName; //记录构造函数注入属性,对应bean属性constructor-arg @Nullable private ConstructorArgumentValues constructorArgumentValues; //Bean属性的名称以及对应的值,这里不会存放构造函数相关的参数值,只会存放通过setter注入的依赖 @Nullable private MutablePropertyValues propertyValues; //方法重写的持有者,记录lookup-method、replaced-method元素 @Lookup等 @Nullable private MethodOverrides methodOverrides; //init函数的名字 @Nullable private String initMethodName; //destory函数的名字 @Nullable private String destroyMethodName; //是否执行init-method,程序设置 private boolean enforceInitMethod = true; private boolean enforceDestroyMethod = true; //是否是合成类(是不是应用自定义的,例如生成AOP代理时,会用到某些辅助类,这些辅助类不是应用自定义的,这个就是合成类) //创建AOP时候为true private boolean synthetic = false; //Bean的角色,为用户自定义Bean private int role = BeanDefinition.ROLE_APPLICATION; // Bean的描述信息 @Nullable private String description; //the resource that this bean definition came from // 这个Bean哪儿来的 @Nullable private Resource resource; //=====================方法:就不逐一解释了,大部分都是get、set 只贴出一些特殊的 // 其实就是给reource赋值了,使用了BeanDefinitionResource public void setOriginatingBeanDefinition(BeanDefinition originatingBd) { this.resource = new BeanDefinitionResource(originatingBd); } // 上面有赋值,所以get的时候就是返回上面set进来的值 public BeanDefinition getOriginatingBeanDefinition() { return (this.resource instanceof BeanDefinitionResource ? ((BeanDefinitionResource) this.resource).getBeanDefinition() : null); } //克隆Bean的定义信息 @Override public Object clone() { return cloneBeanDefinition(); } public abstract AbstractBeanDefinition cloneBeanDefinition(); }
AbstractBeanDefinition定义了一系列描述Bean画像的属性,通过这个类,可以窥见Bean的某些默认设置(例如默认为单例等)。
从上图可以看出,接下俩需要看具体衍生出来的实现类了,先看RootBeanDefinition、ChildBeanDefinition、GenericBeanDefinition。他们都是AbstractBeanDefinition的直接实现类
GenericBeanDefinition:标准bean definition,通用的
除了具有指定类、可选的构造参数值和属性参数这些其它bean definition一样的特性外,它还具有通过parenetName属性来灵活(动态)设置parent bean definition,而非硬编码作为root bean definition
public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(RootConfig.class); // 向工厂里注册Bean信息 GenericBeanDefinition parentBeanDef = new GenericBeanDefinition(); parentBeanDef.setBeanClass(Parent.class); parentBeanDef.setBeanClassName(Parent.class.getName()); parentBeanDef.setScope(BeanDefinition.SCOPE_SINGLETON); // 就这样,我们可以动态的给子Bean 设置一个父Bean进去 GenericBeanDefinition childBeanDef = new GenericBeanDefinition(); childBeanDef.setParentName(parentBeanDef.getBeanClassName()); childBeanDef.setBeanClass(Child.class); applicationContext.registerBeanDefinition("parent", parentBeanDef); applicationContext.registerBeanDefinition("child", childBeanDef); System.out.println(applicationContext.getBeanDefinition("parent")); System.out.println(applicationContext.getBeanDefinition("child")); //Generic bean with parent 'com.fsx.bean.Parent': class [com.fsx.bean.Child]; scope=;... }
GenericBeanDefinition源码实现非常的的简单,只增加了一个parentName的属性值,其余的实现都在父类AbstractBeanDefinition里
备注:若你是xml配置,最初被加载进来都是一个GenericBeanDefinition,之后再逐渐解析的。
ChildBeanDefinition:子Bean定义信息,依赖于父类RootBeanDefinition
ChildBeanDefinition是一种bean definition,它可以继承它父类的设置,即ChildBeanDefinition对RootBeanDefinition有一定的依赖关系。
(功能和GenericBeanDefinition),所以此处忽略~
从spring 2.5 开始,提供了一个更好的注册bean definition类GenericBeanDefinition,所以以后推荐使用它。
RootBeanDefinition:
一个RootBeanDefinition定义表明它是一个可合并的bean definition:即在spring beanFactory运行期间,可以返回一个特定的bean。但在Spring2.5以后,我们绝大多数情况还是可以使用GenericBeanDefinition来做。
我们非常熟悉的final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);这句代码,就是去合并parent的属性进来,这样体现了继承的强大。属性也才完整。
在 配置文件中可以定义父和子,父用RootBeanDefinition表示, 而子用ChildBeanDefiniton表示,而没有父的就使用 RootBeanDefinition表示。下面看看源码:
//简单的说:在多继承体系中,RootBeanDefinition代表的是当前初始化类的父类的BeanDefinition 若没有父类,那就是它自己嘛 public class RootBeanDefinition extends AbstractBeanDefinition { //BeanDefinitionHolder存储有Bean的名称、别名、BeanDefinition @Nullable private BeanDefinitionHolder decoratedDefinition; // AnnotatedElement 是java反射包的接口,通过它可以查看Bean的注解信息 @Nullable private AnnotatedElement qualifiedElement; //允许缓存 boolean allowCaching = true; //从字面上理解:工厂方法是否唯一 boolean isFactoryMethodUnique = false; //封装了java.lang.reflect.Type,提供了泛型相关的操作,具体请查看: // ResolvableType 可以专题去了解一下子,虽然比较简单 但常见 @Nullable volatile ResolvableType targetType; //缓存class,表明RootBeanDefinition存储哪个类的信息 @Nullable volatile Class<?> resolvedTargetType; //缓存工厂方法的返回类型 @Nullable volatile ResolvableType factoryMethodReturnType; /** Common lock for the four constructor fields below */ final Object constructorArgumentLock = new Object(); //缓存已经解析的构造函数或是工厂方法,Executable是Method、Constructor类型的父类 @Nullable Executable resolvedConstructorOrFactoryMethod; //表明构造函数参数是否解析完毕 boolean constructorArgumentsResolved = false; //缓存完全解析的构造函数参数 @Nullable Object[] resolvedConstructorArguments; //缓存待解析的构造函数参数,即还没有找到对应的实例,可以理解为还没有注入依赖的形参 @Nullable Object[] preparedConstructorArguments; /** Common lock for the two post-processing fields below */ final Object postProcessingLock = new Object(); //表明是否被MergedBeanDefinitionPostProcessor处理过 boolean postProcessed = false; //在生成代理的时候会使用,表明是否已经生成代理 @Nullable volatile Boolean beforeInstantiationResolved; //实际缓存的类型是Constructor、Field、Method类型 @Nullable private Set<Member> externallyManagedConfigMembers; //InitializingBean中的init回调函数名——afterPropertiesSet会在这里记录,以便进行生命周期回调 @Nullable private Set<String> externallyManagedInitMethods; //DisposableBean的destroy回调函数名——destroy会在这里记录,以便进行生命周期回调 @Nullable private Set<String> externallyManagedDestroyMethods; //===========方法(只例举部分) // 由此看出,RootBeanDefiniiton是木有父的 @Override public String getParentName() { return null; } @Override public void setParentName(@Nullable String parentName) { if (parentName != null) { throw new IllegalArgumentException("Root bean cannot be changed into a child bean with parent reference"); } } // 拿到class类型 @Nullable public Class<?> getTargetType() { if (this.resolvedTargetType != null) { return this.resolvedTargetType; } ResolvableType targetType = this.targetType; return (targetType != null ? targetType.resolve() : null); } @Override public RootBeanDefinition cloneBeanDefinition() { return new RootBeanDefinition(this); } }
可以看到许多与反射相关的对象,这说明spring底层采用的是反射机制
总结一下,RootBeanDefiniiton保存了以下信息:
1.定义了id、别名与Bean的对应关系(BeanDefinitionHolder)
2.Bean的注解(AnnotatedElement)
3.具体的工厂方法(Class类型),包括工厂方法的返回类型,工厂方法的Method对象
4.构造函数、构造函数形参类型
5.Bean的class对象
可以看到,RootBeanDefinition与AbstractBeanDefinition是互补关系,RootBeanDefinition在AbstractBeanDefinition的基础上定义了更多属性,初始化Bean需要的信息基本完善