Spring scope =`prototype`:如何更改所有bean实例?

时间:2013-11-29 15:00:05

标签: java spring singleton prototype design-patterns

我是一个简单的类,它执行一些Regex模式的再次检查列表。我的模式以某种方式设置了常量值列表。这不是现在的问题,所以我省略了设置代码。

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创建类。

访问patterns同步:

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块中。由于我的课程相当轻量级,我想为每个帖子创建单独的实例(例如,将范围从singleton更改为prototype)。删除同步块并添加getInstance支持的ThreadLocal工厂方法。像那样:

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实例。但还有其他更多的springy方式吗?

1 个答案:

答案 0 :(得分:1)

这是我的建议。 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;
    }
}