For a long time I believed that there was a value in having a "centralized, declarative, configuration" like the xml files we all used to use. Then I realized that most of the stuff in the files wasn't configuration - it was never changed anywhere after development, ever. Then I realized that "centralized" only has value in quite small systems - only in small systems will you ever be able to grok a configuration file as a whole. And what is really the value of understanding the wiring as a whole, when the same "wirings" are mostly duplicated by dependencies in the code? So the only thing I've kept is meta-data (annotations), which is still kind-of declarative. These never change at runtime and they're never "configuration" data that someone will change on the fly - so I think keeping it in the code is nice.
I use full auto-wiring as much as I can. I love it. I won't go back to old-style spring unless threatened at gun-point. My reasons for preferring fully @Autowired
have changed over time.
Right now I think the most important reason for using autowiring is that there's one less abstraction in your system to keep track of. The "bean name" is effectively gone. It turns out the bean name only exists because of xml. So a full layer of abstract indirections (where you would wire bean-name "foo" into bean "bar") is gone. Now I wire the "Foo" interface into my bean directly, and implementation is chosen by run-time profile. This allows me to work with code when tracing dependencies and implementations. When I see an autowired dependency in my code I can just press the "go to implementation" key in my IDE and up comes the list of known implementations. In most cases there's just one implementation and I'm straight into the class. Can't be much simpler than that, and I always know exactly what implementation is being used (I claim that the opposite is closer to the truth with xml wiring - funny how your perspective changes!)
Now you could say that it's just a very simple layer, but each layer of abstraction that we add to our systems increase complexity. I really don't think the xml ever added any real value to any system I've worked with.
Most systems I've ever work with only have one configuration of the production runtime environment. There may be other configurations for test and so on.
I'd say that full autowiring is the ruby-on-rails of spring: It embraces the notion that there's a normal and common usage pattern that most use cases follow. With XML configuration you permit a lot of consistent/inconsistent configuration usage that may/may not be intended. I've seen so much xml configuration go overboard with inconsistencies - does it get refactored together with the code ? Thought not. Are those variations there for a reason? Usually not.
We hardly use qualifiers in our configuration, and found other ways to solve these situations. This is a clear "disadvantage" we encounter: We've slightly changed the way we code to make it interact smoother with autowiring: A customer repository no longer implements the generic Repository<Customer>
interface but we make an interface CustomerRepository
that extends Repository<Customer>
. Sometimes there's also a trick or two when it comes to subclassing. But it usually just points us in the direction of stronger typing, which I find is almost always a better solution.
But yes, you're tying to a particular style of DI that mostly spring does. We don't even make public setters for dependencies any more (So you could argue that we're +1 in the encapsulation/information hiding department) We still have some xml in our system, but the xml basically only contains the anomalies. Full autowiring integrates nicely with xml.
The only thing we need now is for the @Component
, @Autowired
and the rest to be included in a JSR (like JSR-250), so we don't have to tie in with spring. This is the way things have been happening in the past (the java.util.concurrent
stuff springs to mind), so I wouldn't be entirely surprised if this happened again.
The JUnit way is to do this at run-time is org.junit.Assume
.
@Before
public void beforeMethod() {
org.junit.Assume.assumeTrue(someCondition());
// rest of setup.
}
You can do it in a @Before
method or in the test itself, but not in an @After
method. If you do it in the test itself, your @Before
method will get run. You can also do it within @BeforeClass
to prevent class initialization.
An assumption failure causes the test to be ignored.
Edit: To compare with the @RunIf
annotation from junit-ext, their sample code would look like this:
@Test
public void calculateTotalSalary() {
assumeThat(Database.connect(), is(notNull()));
//test code below.
}
Not to mention that it is much easier to capture and use the connection from the Database.connect()
method this way.
Best Answer
Both
@Autowired
(or@Inject
) and@Resource
work equally well. But there is a conceptual difference or a difference in the meaning@Resource
means get me a known resource by name. The name is extracted from the name of the annotated setter or field, or it is taken from the name-Parameter.@Inject
or@Autowired
try to wire in a suitable other component by type.So, basically these are two quite distinct concepts. Unfortunately the Spring-Implementation of
@Resource
has a built-in fallback, which kicks in when resolution by-name fails. In this case, it falls back to the@Autowired
-kind resolution by-type. While this fallback is convenient, IMHO it causes a lot of confusion, because people are unaware of the conceptual difference and tend to use@Resource
for type-based autowiring.