Spring宣言トランザクションソースプロファイル(上)
背景
主な目的は以下の問題を解決することである.
この問題を解決するには、次の2つの問題を解決する必要があります.
本文は主に最初の問題を解決する.
spring xmlファイル解析の準備
spring xmlファイルの解析では、解析するコードの断片は次のとおりです.
対応するspring.xmlコンテンツの断片は次のとおりです.
本文は主にspringがどのようにxmlファイルを解析するかを分析し、対応するbeanデータ構造BeanDefinition.を生成する.読むとき、一つの問題がある.
まずspring解析ラベルコードを見てから、解析ラベルコードを見ます.springコードバージョンv.4.2.4.RELEASE. ClassPathXmlApplicationContextコンストラクタ ClasspathXmlApplicationContext.refresh() AbstractApplicationContext.obtainFreshBeanFactoryこの方法は最後にC o n f i g u r a bleListableBeanFactoryが実現した例を返し、私たちのすべてのbeanは最終的にこの容器にロードされ、その後続行する. AbstractApplicationContext.refreshBeanFactory() AbstractRefreshableApplicationContext.refreshBeanFactory
この方法では、クラス定義のDefaultListableBeanFactoryインスタンスをインスタンス化します.
ここでは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) XmlBeanDefinitionReader.registerBeanDefinitions(Document doc,Resource resource)
BeanDefinitionDocumentReaderに仕事を転嫁する BeanDefinitionDocumentReader.registerBeanDefinitions(Document doc,XmlReaderContext readerContxt) DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(Document doc,XmlReaderContext readerContxt) DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root) DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root,BeanDefinitionParserDelegate delegate)
解析はここで分岐する、デフォルトnamespace(デフォルトnamespaceはbeansを指す)ではparseDefaultElementを呼び出し、そうでなければdelegate.parseCustomElementを呼び出す.トランザクションの構成を理解するため、ここでdelegate.parseCustomElementメソッドにフォローする. BeanDefinitionParserDelegate.parseCustomElement(Element ele) BeanDefinitionParserDelegate.parseCustomElement(Element ele,BeanDefition containingBd);
この方法では、対応するnamespaceのNamespaceHandlerを取得してxmlファイル解析を行い、springの異なるnamespaceのラベルを解決したHandlerである.現在、対応するNamespaceHandlerに作業を転嫁している.私は今、どのように解析するかを知りたいので、対応するNamespaceHandlerはAopNamespaceHandlerである. AopNamespaceHandler.init() 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メソッド 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)
これでspringがxmlをどのように解析し、対応するaopを生成するために必要なbeanについて理解しました.ここではspringがbeanをどのようにロードするかをざっと理解しただけで、各beanについて細かく解析するには、自分でソースコードを見るしかありません.次の編ではTransactionInterceptorがどのようにトランザクションブロックを行うかを詳しく見てみましょう.
主な目的は以下の問題を解決することである.
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.
, spring , bean
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
この方法では、クラス定義のDefaultListableBeanFactoryインスタンスをインスタンス化します.
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable
ここではBeanDefinitionRegistryというインタフェースに注意してください.その役割は、対応するbeanをコンテナに動的に登録することができます.このインタフェースのため、後で対応するbeanをDefaultListableBeanFactoryコンテナインスタンスに登録することができます.
w3c api xml , :
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);
}
// n catch
} 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;
}
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;
}
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メソッドにフォローする.
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 ,
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
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を見つけることができます.
@Override
public void init() {
registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
}
@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がどのようにトランザクションブロックを行うかを詳しく見てみましょう.