如何在ActFramework中创建单例

Java中创建单例是一个有趣的话题 人们对此进行了很多讨论.

常规方法

自从有了Java 5之后创建单例就变得及其简单了:

  1. public enum MySingleton {
  2. INSTANCE;
  3. // your class implementation starts here
  4. public String foo() {
  5. return "foo"
  6. }
  7. }

引用单例的方法:

  1. String s = MySingleton.INSTANCE.foo();

如果你的单例需要继承其他类,你就不能使用enum方式。这个时候你可以使用老方法:

  1. public class MySingleton extends MyBaseClass {
  2. public static final MySingleton INSTANCE = new MySingleton();
  3. }

如果希望INSTANCE私有的话:

  1. public class MySingleton extends MyBaseClass {
  2. private static final MySingleton INSTANCE = new MySingleton();
  3. public static MySingleton instance() {
  4. return INSTANCE;
  5. }
  6. public String foo() {
  7. return "foo"
  8. }
  9. }

或者说你希望延迟加载的话:

  1. public class MySingleton extends MyBaseClass {
  2. private static volatile final MySingleton INSTANCE;
  3. public static MySingleton instance() {
  4. if (null == INSTANCE) {
  5. synchronized(MySingleton.class) {
  6. if (null == INSTANCE) {
  7. INSTANCE = new MySingleton();
  8. }
  9. }
  10. }
  11. return INSTANCE;
  12. }
  13. }

提示 你需要在INSTANCE申明上引入volatile关键字,否则就会落入双锁检查陷阱

ActFramework特别支持

在ActFramework你还有一种简单的使用单例模式的办法,在类申明上加入javax.inject.Singleton注解:

  1. @javax.inject.Singleton
  2. public class MySingleton extends MyBaseClass {
  3. public String foo() {
  4. return "foo"
  5. }
  6. }

使用单例对象:

  1. String s = act.app.App.instance().singleton(MySingleton.class).foo();

如果你的类不需要继承其他类的话你也可以考虑直接继承act.util.SingletonBase

  1. public class MySingleton extends act.util.SingletonBase {
  2. public String foo() {
  3. return "foo"
  4. }
  5. }

这个方法和javax.inject.Singleton注解效果是一样的,而且引用单例对象变得更加简单:

  1. MySingleton singleton = MySingleton.instance();
  2. String s = singleton.foo();
  3. // you can also use the App.singleton(Class) way to fetch your singleton:
  4. MySingleton singleton2 = act.app.App.instance().singleton(MySingleton.class);
  5. // or you can just ask App to give you an new instance:
  6. MySingleton singleton3 = act.app.App.instance().getInstance(MySingleton.class);

上面的代码中,ActFramework确保singleton, singleton2singleton3 都指向同一个实例。你还可以把单例注入到其他类中:

  1. public class MySingletonConsumer {
  2. @Inject
  3. private MySingleton mySingleton;
  4. }

或者注入到你的响应器方法中:

  1. @GetAction("/foo")
  2. public String sayFoo(MySingleton mySingleton) {
  3. return mySingleton.foo();
  4. }

总结

  • 创建单例最简明的方法是把你的类申明为enum
  • ActFramework识别javax.inject.Singleton注解并自动加载单例实例到内存。应用程序可以使用act.app.App.instance().singleton(Class)调用来获取单例
  • ActFramework实现了单例注入
  • ActFramework提供SingletonBase类。如果应用类继承了SingletonBase,单例可以通过MySingleton.instance()调用来获取