1. 程式人生 > >手動編寫spring快取管理器

手動編寫spring快取管理器

引入spring快取依賴
 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>       
 <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>

package com.us.example.config;

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.guava.GuavaCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Created by yangyibo on 17/3/2.
 */
@Configuration
@EnableCaching
public class CacheConfig {
    //此方法是在容器啟動時候把所有的查詢物件放入快取中。
    /*@Bean
    public CacheManager getCacheManager() {
        List<Person> personList = demoService.findAll();
        //所有快取的名字
        List<String> cacheNames = new ArrayList();
        GuavaCacheManager cacheManager = new GuavaCacheManager();
        //GuavaCacheManager 的資料結構類似  Map<String,Map<Object,Object>>  map =new HashMap<>();

        //將資料放入快取
        personList.stream().forEach(person -> {
            //用person 的id cacheName
            String cacheName=person.getId().toString();
            if(cacheManager.getCache(cacheName)==null){
                //為每一個person 如果不存在,建立一個新的快取物件
                cacheNames.add(cacheName);
                cacheManager.setCacheNames(cacheNames);
            }
            Cache cache = cacheManager.getCache(cacheName);
            //快取物件用person的id當作快取的key 用person 當作快取的value
            cache.put(person.getId(),person);
            System.out.println("為 ID 為"+cacheName+ "的person 資料做了快取");
        });
        return cacheManager;
    }*/

    //此方法在容器啟動時候只是初始化快取管理器
    @Bean
    public GuavaCacheManager getCacheManager() {
        //建立快取管理器
        GuavaCacheManager cacheManager = new GuavaCacheManager();
        //GuavaCacheManager 的資料結構類似  Map<String,Map<Object,Object>>  map =new HashMap<>();
        return cacheManager;
    }
}

二:

初始化資料來源
package com.us.example.config;

/**
 * Created by yangyibo on 17/1/13.
 */
import java.beans.PropertyVetoException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import com.mchange.v2.c3p0.ComboPooledDataSource;

@Configuration
public class DBConfig {
    @Autowired
    private Environment env;

    @Bean(name="dataSource")
    public ComboPooledDataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(env.getProperty("ms.db.driverClassName"));
        dataSource.setJdbcUrl(env.getProperty("ms.db.url"));
        dataSource.setUser(env.getProperty("ms.db.username"));
        dataSource.setPassword(env.getProperty("ms.db.password"));
        dataSource.setMaxPoolSize(20);
        dataSource.setMinPoolSize(5);
        dataSource.setInitialPoolSize(10);
        dataSource.setMaxIdleTime(300);
        dataSource.setAcquireIncrement(5);
        dataSource.setIdleConnectionTestPeriod(60);

        return dataSource;
    }
}

三:配置JPA持久層配置類

package com.us.example.config;

import java.util.HashMap;
import java.util.Map;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * Created by yangyibo on 17/1/13.
 */

@Configuration
@EnableJpaRepositories("com.us.example.dao")
@EnableTransactionManagement
@ComponentScan
public class JpaConfig {
    @Autowired
    private DataSource dataSource;

    @Bean
    public EntityManagerFactory entityManagerFactory() {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        //vendorAdapter.setShowSql(true);
        //vendorAdapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setJpaVendorAdapter(vendorAdapter);
        factory.setPackagesToScan("com.us.example.bean");
        factory.setDataSource(dataSource);


        Map<String, Object> jpaProperties = new HashMap<>();
        jpaProperties.put("hibernate.ejb.naming_strategy","org.hibernate.cfg.ImprovedNamingStrategy");
        jpaProperties.put("hibernate.jdbc.batch_size",50);
        //jpaProperties.put("hibernate.show_sql",true);

        factory.setJpaPropertyMap(jpaProperties);
        factory.afterPropertiesSet();
        return factory.getObject();
    }

    @Bean
    public PlatformTransactionManager transactionManager() {

        JpaTransactionManager txManager = new JpaTransactionManager();
        txManager.setEntityManagerFactory(entityManagerFactory());
        return txManager;
    }
}

四:查詢測試首次查詢走資料庫。然後快取物件。再次查詢從快取中取。命中這不走資料庫

package com.us.example.service;

import com.us.example.bean.Person;
import com.us.example.dao.PersonRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.guava.GuavaCacheManager;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by yangyibo on 17/3/2.
 */
@Service
public class PersonService {


    @Autowired
    private GuavaCacheManager cacheManager;

    @Autowired
    private PersonRepository personRepository;


    public Person findOne(Long id) {
        Person person = getCache(id, cacheManager);
        if (person != null) {
            System.out.println("從快取中取出:" + person.toString());
        } else {
            person = personRepository.findOne(id);
            System.out.println("從資料庫中取出:" + person.toString());
            putCache(person);
            System.out.println("物件放入快取中:" + person.toString());
        }
        return person;
    }

    public Person save(Person person) {
        Person p = personRepository.save(person);
        return p;
    }


    public Person getCache(Long id, CacheManager cacheManager) {
        Person person = null;
        Cache cache = cacheManager.getCache(id.toString());
        Cache.ValueWrapper valueWrapper = cache.get(id);
        if(valueWrapper!=null){
            person = (Person) valueWrapper.get();
        }
        return person;
    }

    public void putCache(Person person) {
        List<String> cacheNames = new ArrayList();
        String cacheName=person.getId().toString();
        if(cacheManager.getCache(cacheName)==null){
            //為每一個person 如果不存在,建立一個新的快取物件
            cacheNames.add(cacheName);
            cacheManager.setCacheNames(cacheNames);
        }
        Cache cache = cacheManager.getCache(cacheName);
        cache.put(person.getId(),person);
    }
}

紅色標註的程式碼即為快取的具體邏輯