Spring cacheManager不是单例吗?

时间:2013-02-09 15:24:26

标签: java spring inversion-of-control

我在Spring AnnotationConfigApplicationContext中遇到了一些问题。

主要目的是创建一个可以在应用程序服务器上运行或独立运行的Spring配置。子任务从这个子上下文创建子上下文,该子上下文将由同一AppServer上的另一个应用程序使用。 但是在cacheManager上遇到了一些麻烦。

这是我的代码: aka AbstractConfig

package org.zib.test.a;


import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;


@Configuration
@EnableCaching
public class ConfigA {

    @SuppressWarnings("UnusedDeclaration")
    public static ApplicationContext getContext() {
        return ContextA.getInstance().getContext();
    }


/**
 * use {@link org.zib.test.b.ContextB}
 */
public static <T> T getBean(Class<T> bean) {
    return ContextB.getInstance().getContext().getBean(bean);
}
/**
 * use {@link ContextB}
 */
public static <T> T getBean(String name, Class<T> bean) {
    return ContextB.getInstance().getContext().getBean(name, bean);
}

    @Bean(name = "cacheManager")
    public CacheManager cacheManager() {
        // configure and return an implementation of Spring's CacheManager SPI
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        cacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("default")));
        return cacheManager;
     }

 }

aka AbstractContext

package org.zib.test.a;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ContextA {
    private ApplicationContext applicationContext;

    public static ContextA instance;

    public static ContextA getInstance() {
        synchronized (ContextA.class) {
            if (instance == null)
                instance = new ContextA();
        }
        return instance;
    }

    private ContextA() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(ConfigA.class);
        applicationContext.registerShutdownHook();
        applicationContext.refresh();
        this.applicationContext = applicationContext;
    }

    public ApplicationContext getContext() {
        return applicationContext;
    }
}

模式配置(例如,WebLogicConfig)

package org.zib.test.b;

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.*;
import org.zib.test.a.ConfigA;


@Configuration
@EnableCaching
@Import(ConfigA.class)
public class ConfigB {

    @SuppressWarnings("UnusedDeclaration")
    public static ApplicationContext getContext() {
        return ContextB.getInstance().getContext();
    }
    /**
     * use {@link ContextB}
     */
    public static <T> T getBean(Class<T> bean) {
        return ContextB.getInstance().getContext().getBean(bean);
    }
    /**
     * use {@link ContextB}
     */
    public static <T> T getBean(String name, Class<T> bean) {
        return ContextB.getInstance().getContext().getBean(name, bean);
    }
}

上下文:

package org.zib.test.b;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.zib.test.a.ContextA;

public class ContextB {
    private ApplicationContext applicationContext;

    public static ContextB instance;

    public static ContextB getInstance() {
        synchronized (ContextB.class) {
            if (instance == null)
                instance = new ContextB();
        }
        return instance;
    }

    private ContextB() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(ConfigB.class);
        applicationContext.setParent(ContextA.getInstance().getContext());
        applicationContext.registerShutdownHook();
        applicationContext.refresh();
        this.applicationContext = applicationContext;
    }

    public ApplicationContext getContext() {
        return applicationContext;
    }
}

最终 - 模块配置:

package org.zib.test.c;


import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;


@Configuration
@EnableCaching
public class ConfigC {

    @SuppressWarnings("UnusedDeclaration")
    public static ApplicationContext getContext() {
        return ContextC.getInstance().getContext();
    }
    /**
     * use {@link ContextC}
     */
    public static <T> T getBean(Class<T> bean) {
        return ContextC.getInstance().getContext().getBean(bean);
    }

    /*DELTE BY SUGGESTION OF Tomasz Nurkiewicz
    @Bean(name = "cacheManager")
    public CacheManager cacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        cacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("default")));
        return cacheManager;
    }*/
}

及其背景:

package org.zib.test.c;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.zib.test.a.ContextA;
import org.zib.test.b.ContextB;

public class ContextC {
    private ApplicationContext applicationContext;

    public static ContextC instance;

    public static ContextC getInstance() {
        synchronized (ContextC.class) {
            if (instance == null)
                instance = new ContextC();
        }
        return instance;
    }

    private ContextC() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(ConfigC.class);
        applicationContext.setParent(ContextA.getInstance().getContext());
        applicationContext.registerShutdownHook();
        applicationContext.refresh();
        this.applicationContext = applicationContext;
    }

    public ApplicationContext getContext() {
        return applicationContext;
    }
}

我的测试班:

package org.zib.test;

import org.springframework.cache.CacheManager;
import org.zib.test.a.ConfigA;
import org.zib.test.c.ConfigC;

public class Test {
    public static void main(String[] args) {
        Object cm1 = ConfigC.getBean(CacheManager.class);
        Object cm2 = ConfigA.getBean(CacheManager.class);

        if (cm1 == cm2)
            System.out.println("equals");
        else
            System.out.println("unequal");
    }
}

我已经花了很多时间来解决这个问题 - 如果有人帮助我会很高兴

1 个答案:

答案 0 :(得分:0)

如果我理解正确A是包含两个孩子的父语境:BC。您定义cacheManager两次:在父ConfigA和一个子ConfigC中。不同的应用程序上下文可以具有相同的bean,这就是为什么你得到两个不同的实例。

换句话说,如果您从cacheManager请求ConfigC,它将返回在该上下文中定义的ConfigB。但是,如果您从ConfigAConfigA提出请求,则会从{{1}}(其他实例)返回一个。

它们仍然是单身,但在单个应用程序上下文的范围内。 BTW你能用这个非常复杂的架构来描述你想要实现的目标吗?