Spring Framework: Best Programming Practices Part 2

ベストプラクティスその2!
その2もSpringコアパッケージとその他便利パッケージにフォーカス。
その1~5も参考にどうぞ。
あ、間違ってたら教えて。
(This is the second part of Spring Best Practices series as per Best practices introduction post. This second part is also related with the best practices when using Spring’s Core classes and other utilities. You can refer the other four posts through this links… Part 1, Part 3, Part 4 and Part 5. I am expecting the corrections (if any)as well as the new best ways from my readers.)
--------------------------------------------------------------------------------
* 異なるロケーションでのApplicationContextの設定
* Configuring Spring Application context for different locations:
--------------------------------------------------------------------------------
開発マシン以外の環境設定が同じなら、違うやつだけを定義した別設定ファイルを用意。
(If the configuration is the same for all the environments except for the developer’s machine,
then make (a) separate configuration file(s) with the configuration that is different. )

で、違うやつの設定で、共通のやつを上書きするような定義をする。
(Let this different configuration overwrite the definition(s) in the original file(s).)
注意:上書きした設定は、親設定を参照して他の奴らにも影響するからね。
Make sure this different configuration will never be placed in the other environments!!!
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
Example of how to achieve this if you use the org.springframework.context.support.ClassPathXmlApplicationContext:
※便宜上、Beanには全部ユニークなIDを割り振り中。後でRefし易いように。
(Note: I give every example file below a unique name, so I can easily refer to it.Contents of beanRefContext.xml:)
<'beans>
  <'bean
    id=”aBeanId”class=”org.springframework.context.support.ClassPathXmlApplicationContext”>
    <'constructor-arg>
      <'list>
        <'value>
          /spring/applicationContext-forAllTheEnvironments.xml
        <'/value>
        <'value>/spring/applicationContext-local.xml<'/value>
      <'/list>
    <'/constructor-arg>
    <'constructor-arg>
      ref bean=”frameworkApplicationContextId”/>
    <'/constructor-arg>
  <'/bean>
<'/beans>
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
configLocations(1っこめのコンストラクタ引数)に定義したBeanで、applicationContext(2こめのコンストラクタ引数)に定義したBeanを上書き。
(Beans defined in the config locations (first constructor-arg) overwrite the beans in the parent application context (second constructor-arg).)
このクラスのJavaDocによれば、複数のcouficLocationがある場合、後に定義されたBeanが、先に定義されたものを上書く。他のXMLファイルを経由したBeanでも上書き可能。
(Quote from the JavaDoc of this class “In case of multiple config locations, later bean definitions will override ones defined in earlier loaded files.
This can be leveraged to deliberately override certain bean definitions via an extra XML file.”

--------------------------------------------------------------------------------
* 動的ポイントカットより静的ポイントカット
* Prefer static pointcut over dynamic point cut :
--------------------------------------------------------------------------------
XXX
In Spring’s book of definitions static point cut refers to a pointcut that can be evaluated when a proxy is created.
Criteria for static point cuts can not changed afterwards.
Dynamic point cuts depend on runtime information such as arguement values or call stack.
Dynamic pointcuts are slower to evaluate than static pointcuts and allow less potential for optimization.
It’s always necessary to evaluate them on each invocation.


--------------------------------------------------------------------------------
* Use regular expression advisors to fine tune interceptor scope
--------------------------------------------------------------------------------
TODO
Instead of using broad method point cuts and filtering target methods in interceptor,
use more sophisticated and elegant regular expression at the application context level.
Spring supports three types of regex method point cuts:
・ org.springframework.aop.support.JdkRegexpMethodPointcut : Java 1.4 regular expression for the fully-qualified method names to match.
・ org.springframework.aop.support.Perl5RegexpMethodPointcut : Perl5 regular expression for the fully-qualified method names to match
・ org.springframework.aop.support.RegexpMethodPointcutAdvisor : Convenient class for regexp method pointcuts that hold an Advice, making them an Advisor.
By default, JdkRegexpMethodPointcut will be used on JDK 1.4+, falling back to Perl5RegexpMethodPointcut on JDK 1.3 (requiring Jakarta ORO on the classpath).

・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
Example:
<'bean id=”crudInterceptor” class=”com.mycompany.CrudInterceptor” />
<'bean
  id=”crud”class=”org.springframework.aop.support.RegexpMethodPointcutAdvisor”>
  <'property name=”advice”>
    <'ref local=” crudInterceptor “ />
  <'/property>
  <'property name=”patterns”>
    <'value>.*create.*,.*destroy.*,.*get.*,.*update.*<'/value>
  <'/property>
<'/bean>
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
--------------------------------------------------------------------------------
* 大きいアプリにはオートプロキシが有効
* Use autoproxying for large applications
--------------------------------------------------------------------------------
ProxyFactoryBeanは、小さいアプリにはよいが、設定がくどい。
コントローラごとに違ったプロキシの設定が可能。
プロキシでコード軽減!
SpringのTransactionProxyFactoryBeanや LocalStatelessSessionProxyFactoryBeanで、ProxyFactoryBeanが楽に使える。
(ProxyFactoryBean works well for small application but it requires more verbose configuration.
It allows control over every aspect of the proxy.
Spring ease the use of ProxyFactoryBean by providing dedicated proxies such as TransactionProxyFactoryBean and LocalStatelessSessionProxyFactoryBean.
Proxies also saves code duplication in configurations.)

・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
Example:
<'bean id=”myProxy”
  class=”org.springframework.aop.framework.ProxyFactoryBean”
  abstract=”true”>
  <'property name=”interceptorNames”>
    <'list>
      <'value>interceptor1<'/value>
      <'value>interceptor2<'/value>
    <'/list>
  <'/property>
<'/bean>
<'bean id=”mybean” parent=”myProxy”>
  <'property name=”proxyInterfaces”>
    <'value>com.mycompany.mybean<'/value>
  <'/property>
  <'property name=”target”>
    <'bean class=”com.mycompany.MyBeanImpl”>
      <'property name=”name”>
        <'value>Dave<'/value>
      <'/property>
      <'property name=”description”>
        <'value>Good Boy<'/value>
      <'/property>
    <'/bean>
  <'/property>
<'/bean>
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
上記みたいに子供Beanの定義は、myProxyのような特定の定義を継承できる。子供Beanには、さらにプロパティを足すのが普通。proxy interfacesみたいに。
(Here number of child bean definitions can “extend” the myProxy definition, specifying a target, usually inner bean.
They can optionally add further properties, such as proxy interfaces. )


オートプロキシって要は、設定次第で、複数オブジェクトにプロキシしちゃうもので、BeanNameAutoProxyCreatorかDefaultAdvisorAutoProxyCreatorで作成可能。
(Autoproxying means that depending on some configuration, proxying is applied consistently to a number of objects.
Autoproxy can be created using BeanNameAutoProxyCreator or DefaultAdvisorAutoProxyCreator. )

BeanNameAutoProxyCreatorは、複数個のProxyFactoryBeanの代わりに使うんに良くて、DefaultAdvisorAutoProxyCreatorは、パワフル。
(BeanNameAutoProxyCreator is good for replacing several ProxyFactoryBean. DefaultAdvisorAutoProxyCreator is powerful. )
DefaultAdvisorAutoProxyCreatorは、コンテキストに定義した通りに、ターゲットオブジェクトと合致するポイントカットメソッドがあるか、全アドバイザーを監視。BeanNameAutoProxyCreatorのインタセプタのリストに、アドバイザとアドバイス。 DefaultAdvisorAutoProxyCreatorには、アドバイザ。
(It examines all advisors defined in current context for mathcing pointcut methods on target object. Both advisor and advices and be used in BeanNameAutoProxyCreator interceptor list. DefaultAdvisorAutoProxyCreator strictly requires Advisors. )
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
Examples:BeanNameAutoProxyCreator :
<'bean id=”bnProxyCreator”
  class=”org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator”>
  <'property name=”beanNames”>
    <'value>bean1,mybean*<'/value>
  <'/property>
  <'property name=”interceptorNames”>
    <'list>
      <'value>advisor1<'/value>
      <'value>interceptor1<'/value>
    <'/list>
  <'/property>
<'/bean>
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
Examples:DefaultAdvisorAutoProxyCreator :
<'bean id=”daaProxyCreator”
  class=”org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator” />
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
オートプロキシのcreatorのBeanの定義は、アプリのコードや他のFWのオブジェクトからのアクセスには関係なく、他のBean定義の効能を左右するもの。
オートプロキシは、トランザクション定義にも使える。
(An autoproxy creator bean definition is intended to change the effect of other bean definitions,
not for access by application code or other framework objects. Autoproxy can be used to define transactions as well.)
トランザクションのロールバックについて
デフォルトのトランザクションは、ランタイム例外時のみロールバックして、チェックした例外ではしない。
が、必要に応じて、ロールバックさせたい例外をチェックして業務ロジックをロールバックさせるようにするのもヨイ練習。
例外にマイナス記号をつければ、ロールバックされる。
(15. Specify Transaction Rollback:
By default transactions are rolled back only on runtime exceptions and not on checked exceptions.
However it is a good practice to choose specific checked exceptions where you want the transaction to be rolled back based on business needs. Exceptions marked with negative (-) sign cause transaction to be rolled back.)

・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
Example:
<'bean id=”businessBean”
  class=”org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource”>
  <'props>
    <'prop key=”businessMethod1″>
      PROPAGATION_REQUIRES_NEW,ISOLATION_REPEATABLE_READ,-RollBackBusinessException
    <'/prop>
  <'/props>
  <'/property>
<'/bean>
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
ロールバックを回避するためにランタイム例外を設定するのも可だが、意に沿わない動きをしてまわないよう要注意。
(You can even mark runtime exceptions as positive to prevent rollbacks but be careful while doing so as it could have adverse affects.)

--------------------------------------------------------------------------------
* Aware of thread safe issues with AOP advice
--------------------------------------------------------------------------------
アドバイスインスタンスは複数スレッドでよう流用されるから、スレッドセーフかに注意すべし。
例えば、メソッドインタセプタが、ユニークなIDやカウントに対応したものなら、カウントをインクリメントするために、シンクロナイズドされたメソッド変数をスレッドローカルに用意する。
(Advice instances are most often shared among threads, so we need to consider thread safety issues. For example if the method interceptor is responsible for generating unique id or count, then consider using ThreadLocal variable with synchronized method for incrementing the count.)
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
Example:
public class CountingMethodAdvice implements MethodInterceptor {// The next serial number to be assigned
 private static long nextSerialNum = 0;
 private static ThreadLocal serialNum = new ThreadLocal() {
  protected synchronized Object initialValue() {
   return new Long(nextSerialNum++);
  }
 };
 private static long getCount() {
  if(serialNum!=null){
   return ((Long) (serialNum.get())).longValue();
  }
 }
 public Object invoke(MethodInvocation methodInvocation) throws Throwable {
  System.out.println(”This method is called ” + getCount + ” times”);
 }
}
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・


Lijin’s Localhost
http://lijinjoseji.wordpress.com/2007/09/27/spring-framework-best-programming-practices-part-2/

tag : AOP autoproxy XXX Spring

2008-04-23 23:14 : __fw__spring : コメント : 0 : トラックバック : 0 :
コメントの投稿
非公開コメント

« next  ホーム  prev »

search

ad



counter


tag cloud

category cloud