Spring宣言トランザクションソースプロファイル(上)


背景
主な目的は以下の問題を解決することである.
spring     aop           ?

この問題を解決するには、次の2つの問題を解決する必要があります.
1.spring    xml           ?
2.     aop          ?

本文は主に最初の問題を解決する.
1.spring    xml           ?

spring xmlファイル解析の準備
spring xmlファイルの解析では、解析するコードの断片は次のとおりです.
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("/com/test/spring.xml");

対応するspring.xmlコンテンツの断片は次のとおりです.

    
    


    
        
        
        
        
        
    


本文は主にspringがどのようにxmlファイルを解析するかを分析し、対応するbeanデータ構造BeanDefinition.を生成する.読むとき、一つの問題がある.
spring xml    bean      spring   ?

まずspring解析ラベルコードを見てから、解析ラベルコードを見ます.springコードバージョンv.4.2.4.RELEASE.
  • ClassPathXmlApplicationContextコンストラクタ
  • ClasspathXmlApplicationContext.refresh()
           ,  spring       ,             bean     
    // Tell the subclass to refresh the internal bean factory.  
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
  • AbstractApplicationContext.obtainFreshBeanFactoryこの方法は最後にC o n f i g u r a bleListableBeanFactoryが実現した例を返し、私たちのすべてのbeanは最終的にこの容器にロードされ、その後続行する.
  • AbstractApplicationContext.refreshBeanFactory()
  • AbstractRefreshableApplicationContext.refreshBeanFactory

  • この方法では、クラス定義のDefaultListableBeanFactoryインスタンスをインスタンス化します.
        public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
                            implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable
    

    ここではBeanDefinitionRegistryというインタフェースに注意してください.その役割は、対応するbeanをコンテナに動的に登録することができます.このインタフェースのため、後で対応するbeanをDefaultListableBeanFactoryコンテナインスタンスに登録することができます.
  • AbstractRefreshableApplicationContext.loadBeanDefinition
  • A b s t r a c t XmlApplicationContext.loadBeanDefinition(実装)xmlファイル読み込み作業をXmlBeanDefinitionReader
  • に転嫁する
  • A b s t r actXmlApplicationContext.loadBeanDefinitionsここでは各Resourceをループ読み出し、
  • AbstractBeanDefinitionReader.loadBeanDefinitions(String …locations)
  • AbstractBeanDefinitionReader.loadBeanDefinitions(String location)
  • AbstractBeanDefinitionReader.loadBeanDefinitions(String location,Set actualResource)
  • AbstractBeanDefinitionReader.loadBeanDefinitions(Resource… resources)
  • XmlBeanDefinitionReader.loadBeanDefinitions(Resource resource)
  • XmlBeanDefinitionReader.loadBeanDefinitions(EncodedREsource encodedResource)この方法は、対応するResourceをストリーム読み出して、対応するbean
  • をロードする
  • XmlBeanDefinitionReader.doLoadBeanDefinitions(InputSource inputSource,Resource resource)
      w3c api  xml  ,    :
    
    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
        throws BeanDefinitionStoreException {
    try {
        Document doc = doLoadDocument(inputSource, resource);
        return registerBeanDefinitions(doc, resource);
    }
    // n   catch    
    
    }
  • XmlBeanDefinitionReader.registerBeanDefinitions(Document doc,Resource resource)

  • BeanDefinitionDocumentReaderに仕事を転嫁する
        public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
            BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
            int countBefore = getRegistry().getBeanDefinitionCount();
            documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
            return getRegistry().getBeanDefinitionCount() - countBefore;
        }
    
  • BeanDefinitionDocumentReader.registerBeanDefinitions(Document doc,XmlReaderContext readerContxt)
  • DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(Document doc,XmlReaderContext readerContxt)
  • DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root)
           BeanDefinitionParserDelegate
    
    protected void doRegisterBeanDefinitions(Element root) {
    // Any nested  elements will cause recursion in this method. In
    // order to propagate and preserve  default-* attributes correctly,
    // keep track of the current (parent) delegate, which may be null. Create
    // the new (child) delegate with a reference to the parent for fallback purposes,
    // then ultimately reset this.delegate back to its original (parent) reference.
    // this behavior emulates a stack of delegates without actually necessitating one.
    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = createDelegate(getReaderContext(), root, parent);
    
    if (this.delegate.isDefaultNamespace(root)) {
        String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
        if (StringUtils.hasText(profileSpec)) {
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                    profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                return;
            }
        }
    }
    
    preProcessXml(root);
    parseBeanDefinitions(root, this.delegate);
    postProcessXml(root);
    
    this.delegate = parent;
    }
    
  • DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root,BeanDefinitionParserDelegate delegate)
    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    if (delegate.isDefaultNamespace(root)) {
        NodeList nl = root.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element ele = (Element) node;
                if (delegate.isDefaultNamespace(ele)) {
                    parseDefaultElement(ele, delegate);
                }
                else {
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else {
        delegate.parseCustomElement(root);
    }
    }
    

  • 解析はここで分岐する、デフォルトnamespace(デフォルトnamespaceはbeansを指す)ではparseDefaultElementを呼び出し、そうでなければdelegate.parseCustomElementを呼び出す.トランザクションの構成を理解するため、ここでdelegate.parseCustomElementメソッドにフォローする.
  • BeanDefinitionParserDelegate.parseCustomElement(Element ele)
  • BeanDefinitionParserDelegate.parseCustomElement(Element ele,BeanDefition containingBd);
    public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
        String namespaceUri = getNamespaceURI(ele);
        NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
        if (handler == null) {
            error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
            return null;
        }
        return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
    }
    

  • この方法では、対応するnamespaceのNamespaceHandlerを取得してxmlファイル解析を行い、springの異なるnamespaceのラベルを解決したHandlerである.現在、対応するNamespaceHandlerに作業を転嫁している.私は今、どのように解析するかを知りたいので、対応するNamespaceHandlerはAopNamespaceHandlerである.
  • AopNamespaceHandler.init()
     AopNamespaceHandler init  ,    
        public void init() {
        // In 2.0 XSD as well as in 2.1 XSD.
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
    
        // Only in 2.0 XSD: moved to context namespace as of 2.1
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    }
       config  ,  ConfigBeanDefinitionParser
    
  • ConfigBeanDefinitionParser.parse(Element element,ParserContext parserContext)

  • C o n f i g BeanDefinitionParser.configureAutoProxyCreator(ParserContext parserContext,Element element)この方法は、aopカットを自動的にマウントする役割を果たすA s p e c A w a r e AdvisorAutoProxyCreator beanからDefaultListableBeanFactoryインスタンスに注入します.
    ラベルについては、ConfigBeanDefinitionParser.parsePointcut(Element pointcutElement,ParserContext parserContext)メソッドを使用して解析し、DefaultListableBeanFactory.同理解析解析解析解析解析などのラベルを注入します.
    同様にノードに対して、対応するNamespaceHandler、対応するTxNamespaceHandlerを見つけることができます.
  • TxNamespaceHandler.initメソッド
    @Override
    public void init() {
        registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
        registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
        registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
    }
    
  • TxAdviceBeanDefinitionParser.parse()この方法は、親AbstractBeanDefinitionParserにおける
  • を実装する.
  • AbstractBeanDefinitionParser.parse()
  • AbstractBeanDefinitionParser.parseInternal(Element element, ParserContext parserContext)
  • AbstractSingleBeanDefinitionParser.parseInternal(Element element, ParserContext parserContext)
  • A b s t r a c t S ingleBeanDefinitionParser.getBeanClass(Elementelement)この方法はサブクラスで
  • を書き換える.
  • TxAdviceBeanDefinitionParser.getBeanClass(Element element)
    @Override
    protected Class> getBeanClass(Element element) {
    return TransactionInterceptor.class;
    }
    
    TransactionInterceptor      
    @SuppressWarnings("serial")
    public class TransactionInterceptor extends TransactionAspectSupport 
    implements MethodInterceptor, Serializable 
    
                  ,             。
    

  • これでspringがxmlをどのように解析し、対応するaopを生成するために必要なbeanについて理解しました.ここではspringがbeanをどのようにロードするかをざっと理解しただけで、各beanについて細かく解析するには、自分でソースコードを見るしかありません.次の編ではTransactionInterceptorがどのようにトランザクションブロックを行うかを詳しく見てみましょう.