简体   繁体   中英

Finding stateful singleton beans

Today, we found this pattern in our code:

class Foo {
    private List<String> errors;

    public void addError(String error) { ... }
    public List<String> getErrors();
}

While the code seems to work, this is a singleton Spring bean and it's injected in several independent places and the consumers of the bean assume that they each have their own list of errors. So this introduces subtle bugs.

The obvious solution is to educate developers to avoid this kind of error but I was wondering if there is a static or runtime code analysis tool which can find this kind of bug.

For example, a bean postprocessor could analyze the bean before it's returned and look for private fields that aren't @Autowired .

After pouring some more brains (ours and other peoples) on this, we came up with this approach:

  1. Install a BeanPostProcessor which makes sure that all singleton beans (ie where the scope in the bean definition is Singleton ) have the custom annotation @Stateless on the actual bean type.

    We chose a custom annotation instead of reusing @Singleton since we need this functionality elsewhere, too.

    If the annotation is missing, the factory throws an error.

  2. In a unit test, we use ClassPathScanningCandidateComponentProvider with out custom annotation to locate all classes on the classpath. We can then do the complex and expensive tests to make sure the bean has no state that changes after the initial configuration (ie after the autowiring has happened).

The second step could become a little bit easier if we moved the autowired fields into the constructor but we don't like methods that take many, many arguments. It would be nice if Java or an IDE could generate builders from the bean code. Since that's not the case, we stick to autowired fields and/or setters.

You could create a JUnit test that would load your app config. This could combine ListableBeanFactory from here :

Can I dynamically create a List by scanning the beans in a spring configuration file?

with the 'isSingleton' check here :

How to enforce a prototype scope of Spring beans

ie list all the beans in the app context, then check to see which are singletons.

This would let you find all singleton beans...although it wouldn't really prevent your error case where someone treats one of these singletons as if it were not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM