hibernate涂鸦(2)——reflection反射

org.hibernate.annotations.common.reflection.java.JavaXPackage extends JavaXAnnotatedElemen: Hibernate对Package的适配(Adapter pattern

  -- javaReflectionManager: 父类属性

  -- annotatedElement: 父类属性

  -- public JavaXPackage(Package, JavaReflectionManager): 直接调用同参数super构造函数,分别赋值给annotatedElement和javaReflectionManager

org.hibernate.annotations.common.reflection.java.JavaXClass extends JavaXAnnotatedElement: Hibernate对Class的适配(Adapter pattern

  -- javaReflectionManager: 父类属性

  -- annotatedElement: 父类属性

  -- clazz: 同父类的annotatedElement

  -- typeEnvironment

  -- public JavaXClass(Class, TypeEnvironment, JavaReflectionManager): 调用super(Class, JavaReflectionManager),分别赋值给annotatedElement和javaReflectionManager,赋值clazz和typeEnvironment

org.hibernate.annotations.common.reflection.java.generics.IdentityTypeEnvironment implements TypeEnvironment: 饥饿单例,描述唯一类型环境,每个Type都返回它本身

  -- public Type bind(Type): 接口方法,返回Type本身。

org.hibernate.annotations.common.reflection.java.generics.TypeSwitch<T>: 对根据Type进行条件分支的代码进行抽象后得到的默认模板类,使用时继承该类并覆盖其中某些针对具体Type的方法。

  -- public final T doSwitch(Type): 核心方法,根据Type不同switch到其他分支方法,并返回指定的T。

org.hibernate.cfg.annotations.reflection.XMLContext.Default: 内部类,默认构造函数,描述配置的默认值

  -- accessType: 配置持久化工具如何访问对象的属性,AccessType为枚举类型:PROPERTY|FIELD,参考一篇对2种方式分析利弊的文章(回帖也同样不错)

--StringpackageName:包名

--Stringschema:dbschema

--Stringcatalog:dbcatalog

--BooleanmetadataComplete:是否忽略annotation设置,true表示只采用xml设置,忽略ann设置。

--BooleancascadePersist:是否级联持久化

  -- Boolean delimitedIdentifier: 是否使用db的标识界定字符

  -- public void override(Default): 用传入的Default对象的各个属性值(如果存在)更新本对象的属性值。

  -- public boolean canUseJavaAnnotations(): 返回metadataComplete的非,或者在metadataComplete为null是返回true,表示不忽略ann设置。

org.hibernate.cfg.annotations.reflection.XMLContext: 描述整个xml配置的环境,会在JPAMetadataProvider的xmlContext属性初始化时被new出来。 

  -- boolean hasContext: 指示Context是否被建立起来了,属性默认值为false。

  -- globalDefaults: 在addDocument方法里被new Default出来并设置,全局的默认配置。

  -- classOverriding: Map<String, Element>,通过className找到dom4j的节点元,包括"entity","mapped-superclass","embeddable"以及各个地方定义的"entity-listener"。

  -- defaultEntityListeners: List<String>,所有className的列表,只包括"persistence-unit-defaults"节点上定义的"entity-listener"。

  -- defaultElements: List<Element>,所有dom4j节点元素的列表,只放了root节点。

  -- defaultOverriding: Map<String, Default>,通过className找到作用在它之上的Default默认配置,每一个"entity","mapped-superclass","embeddable"都有自己的Default对象。

  -- public Default getDefault(String): 针对传入的className得到从defaultOverriding中得到该类的默认配置。

  -- public Element getXMLTree(String): 针对传入的className得到从classOverriding中得到该类的dom4j节点。

  -- public List<String> addDocument(Document): 核心方法(其他都是get属性的方法),把dom4j的doc(JPA的orm.xml)加入的当前context中,并且返回doc中存在的所有class名字

  1. hasContext置为true
  2. 如果root节点("entity-mappings")包含"persistence-unit-metadata"子节点:并且如果globalDefaults为null,则new Default对象赋值给globalDefaults,然后分析该子节点:
    1. 将"xml-mapping-metadata-complete"子子节点的值赋值给globalDefaults.metadataComplete,不存在的话默认为false;
    2. 如果"persistence-unit-defaults"子子节点存在,则分别读取各个子节点并赋值globalDefaults."schema","catalog","access":accessType,"cascade-persist","delimited-identifiers";遍历"entity-listeners"子子节点下所有"entity-listener"节点,取得"class"属性值,如果classOverriding包含了该属性值:并且如果从classOverriding根据该属性值取出的element节点名字是"entity-listener"的话就log该listener的重复定义然后继续遍历下一个,else则抛出IllegalStateException说明已经定义成entity的类不能再被定义为listener,导致遍历终止;最后将listener放入classOverriding中,而listenerClassName放入defaultEntityListeners列表中。
  3. 用root节点下面的"package","schema","catalog","access"节点构造一个Default对象传入Step5的遍历过程;
  4. 把root节点("entity-mappings")放入到defaultElements列表中;
  5. 分别遍历root下的"entity","mapped-superclass","embeddable"子节点:
    1. 取得每个子节点的"class"属性值,并与root节点下面的"package"节点提供的默认包名构成类的全限定名字,如果classOverriding包含了该className则抛出IllegalStateException说明已经定义成entity的类不能再被定义为另外的entity;else则将该子节点元素放入classOverriding中;
    2. 如果该子节点定义了"metadata-complete"节点或者"access"节点,取出这些节点值并覆盖Step3传入的Default对象,将这个变化后的Defualt对象放入defaultsOverriding中;
    3. 遍历"entity-listeners"子子节点下所有"entity-listener"节点,取得"class"属性值,并与root节点下面的"package"节点提供的默认包名构成类的全限定名字,如果classOverriding包含了该className:并且如果从classOverriding根据该属性值取出的element节点名字是"entity-listener"的话就log该listener的重复定义然后继续遍历下一个,else则抛出IllegalStateException说明已经定义成entity的类不能再被定义为listener,导致遍历终止;最后将listener放入classOverriding中。
  6. 最终return一个包含所有"entity","mapped-superclass","embeddable"以及各个地方定义的"entity-listener"的className列表。

org.hibernate.annotations.common.reflection.java.JavaMetadataProvider: 默认构造函数,在JPAMetadataProvider的metadataProvider属性初始化被new出来,对MetadataProvider接口的最简单实现

  -- public Map<Object, Object> getDefaults(): 返回一个可系列化的并且immutable的空Map,即表明不存在default的metadata。

  -- public AnnotationReader getAnnotationReader(AnnotatedElement): 用传入的有ann的元素构造一个JavaAnnotationReader对象并return。

org.hibernate.annotations.common.reflection.java.JavaAnnotationReader: 唯一参数构造函数,仅在JavaMetadataProvider的getAnnotationReader方法里被new出来,封装了一个ann元素的对象,代理该对象上访问ann的方法。

  -- annotatedElement: 封装一个具有ann定义的类型元素

org.hibernate.cfg.annotations.reflection.JPAMetadataProvider: 默认构造函数,在Configuration的reset方法中被new出来,并设置给JavaReflectionManager的metadataProvider,在JavaMetadataProvider之上增强了JPA metadata的功能(多了Default/XMLContext/cache以及提供一个特有的JPAOverridenAnnotationReader,使得xml配置和ann配置可以统一处理)。

  -- metadataProvider: transient,属性初始化时new JavaMetadataProvider对象放入作为delegate被JPAMetadataProvider代理(Proxy pattern),

  -- xmlContext: metadata的context,属性初始化时new XMLContext对象放入。

  -- cache: transient,Map<AnnotatedElement, AnnotationReader>: 缓存AnnotationReader对象,可以根据被read的具有ann的元素来查找。

  -- public AnnotationReader getAnnotationReader(AnnotatedElement): 用传入的具有ann的元素在cache里查找对应的Reader,找到则return;else找不到则判断xmlContext.hasContext(),如果已经建立的context,则用传入的annotatedElement和xmlContext一起构造出一个JPAOverridenAnnotationReader对象并缓存后return,else没有建立起context,则调用被代理的metadataProvider.getAnnotationReader(传入的annotatedElemen)方法得到一个JavaAnnotationReader对象并缓存后return。

org.hibernate.cfg.annotations.reflection.JPAOverridenAnnotationReader: 仅在JPAMetadataProvider的getAnnotationReader方法里被new出来,比JavaAnnotationReader提供更复杂的功能:在调用AnnotationReader接口定义方法前会先执行initAnnotations方法.

  -- annotatedElement: 封装一个具有ann定义的类型元素,代理了该对象上访问ann的方法。

  -- xmlContext: metadata的context,由JPAMetadataProvider通过构造函数赋值。

  -- annotations: transient,包括annotatedElement上定义的所有ann的集合(有些ann是通过xml配置新构造的)数组,由initAnnotations方法建立并填充。

  -- annotationsMap: transient,Map<Class, Annotation>,和annotations数组放的东西一样,包括annotatedElement上定义的所有ann的集合(有些ann是通过xml配置新构造的),并且以ann的类型为key;同样由initAnnotations方法建立并填充。

  -- annotationToXml: static,Map<Class, String>,通过所有JPA定义的annotation找到对应的xml配置项。会在类初始化时被建立起来并初始化所有对应值。

  -- String className

  -- String propertyName

  -- propertyType: PropertyType为枚举类型:PROPERTY/FIELD/METHOD

  -- public JPAOverridenAnnotationReader(AnnotatedElement, XMLContext): 唯一构造函数:

  1. 对annotatedElement和xmlContext赋值;
  2. 如果传入的element是Class类型,则对className赋值;
  3. 如果传入的element是Field类型,则对className/propertyName分别赋值,propertyType置为Field,并假设存在该field的get方法,取得Method对象后赋值给mirroredAttribute,如果方法不存在,NoSuchMethodException会被吃掉。
  4. 如果传入的element是Method类型,则对className赋值,如果这个Method是某个Field的get/is方法,那么propertyName赋值为Field名字,propertyType置为PROPERTY,并假设存在这个field,取的Field对象后赋值给mirroredAttribute;else情况propertyName赋值为Method名,propertyType置为METHOD。
  5. 其他类型的情况,则置className/propertyName都为null。

  -- private void initAnnotations(): 根据annotatedElement类型不同分别构造对应的annotations数组和annotationsMap以方便在read的时候可以直接读取到和orm.xml的配置融合后的ann

  • 如果className不null并且propertyName为null,说明是class类型的annotatedElement构造的reader,则调用xmlContext.getXMLTree(className)得到dom4j节点,调用xmlContext.getDefault(className)得到Default配置,然后利用Default对象和dom4j节点对象以及annotatedElement上存在的所有ann构造出一个annotations数组和一个annotationsMap,数组和map是一致的,存放规则为:不包含在annotationToXml的类型的ann,以及如果在context里已经通过xml配置了,则被这些xml配置盖后的ann;最后将xml里配置了的attributes,但在具体的class上却没有该field或者property的话,记录log,不做任何处理。
  • 如果className不null并且propertyName也不null,说明是Field/Method类型的annotatedElement构造的reader,@TODO
  • 其他情况,annotations和annotationsMap包含所有在annotatedElement上存在的ann。

org.hibernate.annotations.common.reflection.java.JavaReflectionManager.TypeKey: 静态私有内部类,一个<Type, TypeEnvironment>的Pair结构

org.hibernate.annotations.common.reflection.java.JavaReflectionManager: static初始块里log一下annotation的版本,在Configuration的reset方法中被new出来,并设置给Configuration 的reflectionManager

  -- metadataProvider

  -- packagesToXPackages: Map<Package, JavaXPackage>

  -- xClasses: Map<TypeKey, JavaXClass>

  -- public XPackage packageForName(String) throws ClassNotFoundException: 根据传入的package名字(包中必须存在package-info.java文件)通过反射得到Package对象,把Package对象和this作为参数new出一个JavaXPackage;Package对象为key,JavaXPackage对象为value,在packagesToXPackages找key,找到返回;找不到放value进packagesToXPackages并返回。

  -- public XClass classForName(String className, Class caller) throws ClassNotFoundException: ①toXClass(通过传入caller的CL使用反射得到Class对象)

  -- public XClass toXClass(Class): ②toXClass(传入的Class对象, IdentityTypeEnvironment的实例)

  -- XClass toXClass(Type, TypeEnvironment): 构造一个能特殊处理Class和ParameterizedType两种Type的TypeSwitch<XClass>,其中对待Class的处理方法为:使用传入的Class和TypeEnvironment new一个TypeKey对象作为key,使用Class和TypeEnvironment以及this new一个JavaXClass对象作为value,在xClasses里找该key,找到返回;找不到放value进xClasses并返回。

相关推荐