Correct way of making a singleton a Spring bean

前端 未结 6 775
野性不改
野性不改 2020-12-08 03:12

I am converting a singleton to a Spring bean, so that if the singleton fails to initialize, then entire web application\'s spring context doesn\'t load properly.

Th

相关标签:
6条回答
  • 2020-12-08 03:24

    Why are you using singleton pattern on the first place? Just let Spring create bean for you (with default singleton scope) and... use it. Of course always somebody might create the bean by hand, but this was never a problem in my case.

    Dependency injection and Spring-managed bean lifecycle will ease your life significantly (just see how many pitfalls you can avoid). Also note that exceptions thrown from c-tor or @PostContruct method will propagate and cause application context startup to fail as well.

    UPDATE: I get your point. This is what came in to my mind:

    @Service
    public class Singleton {
    
        private static AtomicReference<Singleton> INSTANCE = new AtomicReference<Singleton>();
    
        public Singleton() {
            final Singleton previous = INSTANCE.getAndSet(this);
            if(previous != null)
                throw new IllegalStateException("Second singleton " + this + " created after " + previous);
        }
    
        public static Singleton getInstance() {
            return INSTANCE.get();
        }
    
    }
    

    And let Spring do its job. You can use DI when possible and Singleton.getInstance() where you have to.

    Also there are more hard-core solutions like compile-time AspectJ weaving and injecting Spring beans basically to everything.

    0 讨论(0)
  • 2020-12-08 03:25

    According to me this is a belts-and-suspenders solution.

    If you create a bean and declare it as a singleton in the configuration then there should be no need to protect the bean against being multiply created.

    You are now basically protecting yourself from someone wrongly configuring the bean.

    I personally would "solve" that by documentation in the spring configuration and Javadoc.

    0 讨论(0)
  • 2020-12-08 03:30

    I'm not sure why you'd want to do this. When you tell Spring that a bean should be a singleton, the corresponding class does not need to be a singleton, and does not need a factory. Spring just simply only ever creates one instance.

    The linked article makes no sense to me, since there is NO injection happening, that I can see: "AnyService" is calling the singleton factory method; that the singleton is referenced in the app context is irrelevant until it's referenced, and it seems no other bean references it.

    0 讨论(0)
  • 2020-12-08 03:30

    To run code at startup (and fail on error) use one of the many ways to register startup events, e.g. see http://www.baeldung.com/running-setup-logic-on-startup-in-spring

    Example:

    @Component
    public class InitializingBeanExampleBean implements InitializingBean {
    
        private static final Logger LOG = Logger.getLogger(InitializingBeanExampleBean.class);
    
        @Autowired
        private Environment environment;
    
        @Override
        public void afterPropertiesSet() throws Exception {
            LOG.info(Arrays.asList(environment.getDefaultProfiles()));
        }
    }
    
    0 讨论(0)
  • 2020-12-08 03:38

    You must declare the INSTANCE field as volatile for double-checked locking to work correctly.

    See Effective Java, Item 71.

    0 讨论(0)
  • 2020-12-08 03:47

    True singleton are hard to get working.

    Volatile double-checked locking also does not work property. Read about it on wiki http://en.wikipedia.org/wiki/Double-checked_locking

    Your best bet is to simply do this

    public class MySingleton {
    
        private static MySingleton INSTANCE = new MySingleton();
    

    That is if you do not have any constructor parameters in your real code.

    0 讨论(0)
提交回复
热议问题