Static util class with Spring, unsure if I should make it a SpringBean, design concerns

3.1k Views Asked by At

Quick high level concept of my design..

CLI tool to create AWS EBS snapshots
CLI tool just calls Java class com.util.SnapshotUtil
com.util.Snapshot calls AWS Interfacing class com.aws.AWSAdapter

example usage from command line..

cli-tool create-snapshot.. calls java class eventually calling below method
SnapshotUtil.createSnapshot() // statically  call AWSAdapter.createSnapshot();

Currently everything is static and outside of Spring.

Now I am wondering if AWSAdapter should not be static, and loaded by Spring, which would mean my SnapshotUtil would need to create the Adapter through ApplicationContext, I believe, as well as supplying it an XML with the Adapter bean info.

Originally I thought since this is a simple util to deal with ebs snapshots, I could ignore Spring, but the AWSAdapter could potentially be used by other means, however, not sure if being static would be a pro or a con.

The Adapter is designed to only deal with an EBS Snapshot, so its basically either creating / deleting / viewing snapshots by using an AmazonEC2Client instance. Even if a Spring managed class wanted to use this Adapter, my question is if it matters if it loads the Adapter through Spring or just statically call it.

edit in response to answer:

I started turning it into a bean and removed all static references, I gave it a method getInstance() which will load itself through applicationContext and return to caller after initializing other dependencies and configurations. When I call this from outside of spring, is that okay? it seems to be working, is it still considered 'injecting'? I am pretty sure its not injecting, since the caller is not spring managed, but I feel this may be hacky? As in, I am using a spring bean in non spring class, so im never spring managed, so I feel there is no reason to turn the utility into a bean. I am still going to do it because I understand the benefits.

One reason I 'have' to turn it into a bean, is that it uses another spring bean I need to handle authenticating, however I thought about it and I could easily just instantiate the other bean using the 'new' keyword.

Am I correct when I say I turned my class into a bean but it is not 'injected' to callers, at least when using the getInstance() method? if I use the getInstance method() in a spring bean, would there be any difference if I were to 'inject' the utility through spring configurations instead?

1

There are 1 best solutions below

0
On BEST ANSWER

Generally, you should favor non-static over static. Regarding your specific example, you should go with Spring beans, because that gives you much more flexibility when you start extending your application/module with more complex features.

For example, very soon static-only classes will require some resources from other parts of the system (and we all know how DI helps here).

Or you will need to advise static invocations with some aspects (be it only simple ones as logging of each request, but think of the more complex cases like transactions). With Spring beans this is very simple to achieve and, very important, simple to add afterwards without a big re-engineering and re-testing.

Also, you will much easier integrate beans with other Spring APIs and frameworks that are already well integrated with Spring. For example, you will easy use your bean in an Apache Camel route.

These are just a few points that came to my mind, there are many more of them. But, as always, consider all the pros and cons and pick the right tool for the job.

Edited part of the question

"When I call this from outside of spring, is that okay?"

Yes, it's fine to obtain the bean instance from the Spring application context directly in a class that is not managed by Spring or when the bean name is not known until runtime. In my example with Apache Camel route, that's exactly what Camel does. :)

"Am I correct when I say I turned my class into a bean but it is not 'injected' to callers, at least when using the getInstance() method?"

Yes, it is still a bean with all of the bean's functionality (with other beans injected in it, with aspects around it, etc).

"If I use the getInstance method() in a spring bean, would there be any difference if I were to 'inject' the utility through spring configurations instead?"

Regarding this, you may take a look at this question and at the article written by Martin Fowler, which is also referenced from the question.

In my opinion, you should not do it, it is less readable and quite unnecessary. Injecting the resources as fields is a type safe and a clean mechanism for a class to declare its dependent resources.

Also, bean lookup may be costly if executed frequently. I experienced this on a project I worked on in the past. I don't know why, but it takes some time for Spring (at least the Spring version we used then) to look up and return the bean, and it is noticeable if executed in a loop.