java - Spring 范围 =`prototype` : how to change all bean instances?

标签 java spring singleton prototype design-patterns

我有一个简单的类,它对正则表达式模式列表执行一些检查。我的模式是通过恒定的值列表以某种方式设置的。目前这不是一个问题,所以我省略了该设置代码。

class Checker {
   private final Pattern [] patterns = new Pattern[10];

   public boolean check(final String param){
     for(Pattern p : patterns){
        if(p.matcher(param).matches())
           return true;
      }
     return false;
   }
} 

事情很简单。 现在我正在从 500 个并发线程访问该类。类是使用默认的 Spring 作用域 singleton 创建的。

同步访问模式:

class Checker {
   private final Pattern [] patterns = new Pattern[10];

   public boolean check(final String param){
     synchronized(patterns){
      for(Pattern p : patterns){
         if(p.matcher(param).matches())
            return true;
      }
     return false;
     }
   }
} 

好吧,由于所有线程都访问我的类的单个实例 - 它们被锁定在同步块(synchronized block)中。由于我的类相当轻量级,我想为每个线程创建单独的实例(例如,将范围从 singleton 更改为 prototype)。删除同步块(synchronized block)并添加由 ThreadLocal 支持的 getInstance 工厂方法。像这样:

class Checker {
   private final Pattern [] patterns = new Pattern[10];

   public boolean check(final String param){
     for(Pattern p : patterns){
        if(p.matcher(param).matches())
           return true;
      }
     return false;
   }

   private static final ThreadLocal<Checker> checkerLocal =
      new ThreadLocal<Checker>() {
       @Override 
       protected Checker initialValue() {
         System.out.println("Creating Checker instance")
         return new Checker();
       }
   };

   public static Checker getInstance(){
          return checkerLocal.get();  
   }
}

就像魅力一样。

但是,想象一下我必须在应用程序内部动态以某种方式修改模式(例如,在其中添加或删除模式)。我应该对 Checker 类的所有现有实例执行此操作。 我正在考虑使用 ApplicationContext#getBeansOfType(Checker.class) 方法来获取所有 bean 实例。但是还有其他更有弹性的方法吗?

最佳答案

这是我的建议。 Checker类根本不需要任何同步,因为它只提取不可修改的 List<Pattern>在持有者类之外,唯一需要的同步是防止持有者上的更新冲突。

public class PatternService {
    AtomicReference<List<Pattern>> patterns = new AtomicReference<>(Collections.emptyList());

    public List<Pattern> getPatterns() {
        return patterns.get();
    }

    public synchronized void addPattern(Pattern p) {
        List<Pattern> newPatterns = new LinkedList<>(patterns.get());
        newPatterns.add(p);
        patterns.set(Collections.unmodifiableList(newPatterns)); // or ImmutableList
    }

    // other mutators
}


public class Checker {
    @Autowired PatternService patternService;

    public boolean check(String param) {
        for(Pattern p: patternService.getPatterns())
            if(p.matcher(param).matches())
                return true;

        return false;
    }
}

关于java - Spring 范围 =`prototype` : how to change all bean instances?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20288494/

相关文章:

java - SPRING MVC - 如何获取表单:input path from JSP to Controller的值

java - Spring Boot 集成测试通过注释加倍?

java - Maven 构建 View 和 XML 文件丢失

头文件中的c++模板单例静态指针初始化

java - 在浏览器中运行java-applet源代码

java - 在 Java 中将远程文件通过 HTTP 转换为输入流

ios - 在共享单例类中添加多个方法会导致任何性能问题吗?

具有匹配静态接口(interface)的 Java 实用程序单例

java - Spring MVC Hibernate 错误 java.lang.Object;无法转换为 model.Employee

java - 应用程序启动时键盘会自动显示吗?