Springキャッシュメカニズムの実例コード


Springのキャッシュメカニズムは非常にフレキシブルであり、容器内の任意のBeanまたはBenの方法をキャッシュすることができるので、このようなキャッシュメカニズムはJavaEEアプリケーションの任意のレベルでキャッシュすることができる。
Springキャッシュの下層も他のキャッシュツールを介して実現される必要があります。例えば、EhCache(Hibernateキャッシュツール)は、上層部が統一APIでプログラムされます。
Springキャッシュを使うには、以下の3つのステップが必要です。
  • 1.Springプロファイルにcontextを導入する:名前空間
  • .Springプロファイルでキャッシュを有効にして、具体的には
  • を追加します。
  • .キャッシュマネージャを配置し、異なるキャッシュ実装構成が異なり、EhCacheであれば、まずehcache.xml
  • を配置する必要がある。
    例えば
    
    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache>
      <diskStore path="java.io.tmpdir" />
      <!--          -->
      <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        maxElementsOnDisk="10000000"
        diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU"/>
      <!--     users     -->
      <cache name="users"
        maxElementsInMemory="10000"
        eternal="false"
        overflowToDisk="true"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600" />
    </ehcache>
    上のehcache.xmlは二つのキャッシュエリアを配置しています。SpringのBeanはこれらのキャッシュエリアにキャッシュされます。一般的に、Spring容器の中にいくつのBenがあり、ehcacheでいくつのキャッシュエリアが定義されますか?
    次にSpringプロファイルにキャッシュマネージャを配置すると、最初のBeanは工場Beanであり、EhCacheを配置するためのCacheManagerであり、第二のBenはSpringキャッシュに配置されたキャッシュマネージャであるため、最初のBenを第二のBenに注入する。
    
    <cache:annotation-driven cache-manager="cacheManager" />
    
      <!--   EhCache CacheManager
        configLocation  ehcache.xml      -->
      <bean id="ehCacheManager"
        class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
        p:configLocation="classpath:ehcache.xml"
        p:shared="false" />
      <!--     EhCache      
        EhCache CacheManager        Bean -->
      <bean id="cacheManager"
        class="org.springframework.cache.ehcache.EhCacheCacheManager"
        p:cacheManager-ref="ehCacheManager" > 
      </bean>
    次は完全なSpring構成です。
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:p="http://www.springframework.org/schema/p"
      xmlns:cache="http://www.springframework.org/schema/cache"
      xmlns:context="http://www.springframework.org/schema/context"
      xsi:schemaLocation="http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
      http://www.springframework.org/schema/cache
      http://www.springframework.org/schema/cache/spring-cache-4.0.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    
      <context:component-scan 
        base-package="com.service"/>
        
      <cache:annotation-driven cache-manager="cacheManager" />
    
      <!--   EhCache CacheManager
        configLocation  ehcache.xml      -->
      <bean id="ehCacheManager"
        class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
        p:configLocation="classpath:ehcache.xml"
        p:shared="false" />
      <!--     EhCache      
        EhCache CacheManager        Bean -->
      <bean id="cacheManager"
        class="org.springframework.cache.ehcache.EhCacheCacheManager"
        p:cacheManager-ref="ehCacheManager" > 
      </bean>
      
    </beans>
    以下では@Cacheableを例にとって、SpringがEhCacheキャッシュに基づく使い方を実証する。Cacheableは、クラスまたは方法を修飾するために用いられ、クラス内のあらゆる方法がキャッシュされる。
    クラスレベルのキャッシュ
    例えば、次のようなBean類があります。
    
    @Service("userService")
    @Cacheable(value="users")
    public class UserServiceImpl implements UserService {
    
      @Override
      public User getUsersByNameAndAge(String name, int age) {
        System.out.println("    getUsersByNameAndAge()..");
        return new User(name,age);
      }
    
      @Override
      public User getAnotherUser(String name, int age) {
        System.out.println("    getAnotherUser()..");
        return new User(name,age);
      }
    }
    クラスのキャッシュに基づいて、キャッシュクラスのすべての方法が、キャッシュされた後に、プログラムは、このクラスのインスタンスのいずれかの方法を呼び出します。入力されたパラメータが同じであれば、Springはこの方法を本当に実行しないで、直接に入力されたパラメータに基づいてキャッシュ中のデータを検索します。
    例えば以下のようにキャッシュデータを使います。
    
    public static void test2() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        UserService us = ctx.getBean("userService", UserService.class);
        User u1 = us.getUsersByNameAndAge("  ", 50);
        //       userService   ,       ,            ,
        //Spring             
        User u2 = us.getAnotherUser("  ", 50);
        System.out.println(u1==u2);
      }
    出力結果、
    getsUsers ByNameAndAgeを実行しています。
    true
    上記のget AnothersUser()は、実際に実行されていないことが分かります。これは、入力されたパラメータが前の方法と同じであるため、Springはキャッシュエリアから直接データを取得しました。
    上記のBeanクラスの注釈@Cacheableは、必須属性valueの他に、key、condition、unless属性、後の三つは、Spring記憶ポリシーを設定するために用いられており、クラスのキャッシュに基づいて、Springはデフォルトでは方法として伝えられたパラメータをkeyキャッシュにおいて検索結果として使用している。
    もちろん、keyのポリシーを変更して、Springを他の基準に合わせて、例えば最初のパラメータが同じかどうかキーとしてキャッシュで検索しても良いです。
    上のビーン類を以下のように修正します。
    
    @Service("userService")
    @Cacheable(value="users", key="#name")
    public class UserServiceImpl implements UserService {
    
      @Override
      public User getUsersByNameAndAge(String name, int age) {
    同じnameが入ってきたという意味で、Springは本当に方法を実行しません。nameが異なる時だけ、方法は本当に実行されます。例えば、以下のように。
    
    public static void test2() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        UserService us = ctx.getBean("userService", UserService.class);
        User u1 = us.getUsersByNameAndAge("  ", 50);
        // @Cacheable key    key="#name"  ,          。
        User u2 = us.getAnotherUser("  ", 50);
        System.out.println(u1==u2);
      }
    今回のgetAnotherUser()方法が実行されたことが見られます。
    1 getsUsersByNameAndAgeを実行しています。
    2 get Another Userを実行しています。
    3 false
    condition属性を設定することもできます。例えば、
    
    @Service("userService")
    @Cacheable(value="users", condition="#age<100")
    public class UserServiceImpl implements UserService {
    
      @Override
      public User getUsersByNameAndAge(String name, int age) {
    次のコードに対しては、両方の方法がキャッシュされません。Springは毎回本当の方法で結果を取ります。
    
    public static void test2() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        UserService us = ctx.getBean("userService", UserService.class);
        User u1 = us.getUsersByNameAndAge("  ", 500);
        User u2 = us.getAnotherUser("  ", 500);
        System.out.println(u1==u2);
      }
    実行結果、
    getsUsers ByNameAndAgeを実行しています。
    get Another Userを実行しています。
    false
    メソッドレベルのキャッシュ
    方法レベルのキャッシュは方法のためだけに機能します。別の方法では不要なキャッシュエリアを設定できます。例えば以下のように、
    
    @Service("userService")
    public class UserServiceImpl implements UserService {
    
      @Cacheable("users1")
      @Override
      public User getUsersByNameAndAge(String name, int age) {
        System.out.println("    getUsersByNameAndAge()..");
        return new User(name,age);
      }
    
      @Cacheable("users2")
      @Override
      public User getAnotherUser(String name, int age) {
        System.out.println("    getAnotherUser()..");
        return new User(name,age);
      }
    }
    下記のテストコードを使って、
    
    public static void test2() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        UserService us = ctx.getBean("userService", UserService.class);
        //       ,           
        User u1 = us.getUsersByNameAndAge("  ", 500);
        //            ,                ,          
        User u2 = us.getAnotherUser("  ", 500);
        System.out.println(u1==u2);
        //       ,        ,      
        User u3 = us.getAnotherUser("  ", 500);
        System.out.println(u3==u2);
      }
    実行結果、
    getsUsers ByNameAndAgeを実行しています。
    get Another Userを実行しています。
    false
    true
    @Cacheevictを使ってキャッシュをクリアします。
    @Cacheevictによって修正された方法はキャッシュをクリアするために用いられ、@CacheEvictを使用して以下のような属性を指定することができる。
    all Entiesはキャッシュエリア全体をクリアしていますか?
    before Invocation:方法を実行する前にキャッシュをクリアするかどうか。デフォルトは方法の実行が成功してからクリアします。
    condiitionおよびkeyは@Cacheableと同じ意味です。
    次のモデルは簡単に使います。
    
    @Service("userService")
    @Cacheable("users")
    public class UserServiceImpl implements UserService {
    	@Override
    	  public User getUsersByNameAndAge(String name, int age) {
    		System.out.println("    getUsersByNameAndAge()..");
    		return new User(name,age);
    	}
    	@Override
    	  public User getAnotherUser(String name, int age) {
    		System.out.println("    getAnotherUser()..");
    		return new User(name,age);
    	}
    	//    name,age      
    	@CacheEvict(value="users")
    	  public void evictUser(String name, int age) {
    		System.out.println("--    "+name+","+age+"     --");
    	}
    	//    user          
    	@CacheEvict(value="users", allEntries=true)
    	  public void evictAll() {
    		System.out.println("--        --");
    	}
    }
    次はテストクラスです。
    
    public static void test2() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        UserService us = ctx.getBean("userService", UserService.class);
        //         
        User u1 = us.getUsersByNameAndAge("  ", 500);
        User u2 = us.getAnotherUser("  ",400);
        //  evictUser()            
        us.evictUser("  ", 400);
        //        , 400    ,                 
        User u3 = us.getAnotherUser("  ", 400);
        System.out.println(us == u3);  //false
        //          , 500   ,          ,         
        User u4 = us.getAnotherUser("  ", 500);
        System.out.println(u1==u4); //  true
        //      
        us.evictAll();
        //            ,            
        User u5 = us.getAnotherUser("  ", 500);
        User u6 = us.getAnotherUser("  ", 400);
        System.out.println(u1==u5); //  false
        System.out.println(u3==u6); //  false
      }
    実行結果、
    getsUsers ByNameAndAgeを実行しています。
    get Another Userを実行しています。
    --李四、400に対応するキャッシュをクリアしています。
    get Another Userを実行しています。
    false
    true
    --キャッシュ全体をクリアしています。
    get Another Userを実行しています。
    get Another Userを実行しています。
    false
    false
    締め括りをつける
    以上が本論文のSpringキャッシュメカニズムの実例コードの全部です。ご協力をお願いします。興味のある方は引き続き当駅の他のテーマを参照してください。友達のサポートに感謝します。