So, if you have a background in conventional programming (and especially if you’re no spring chicken, like myself), then you usually have certain expectations of how programming flow works and how functions are called. Unfortunately, though, if you happen to wander down the path into the land of IoC, nobody will warn you that you’re about to enter a bizzaro world all its own, especially if you’re a fresh grad out of school. You might hear some casual warnings like “Hey, watch yourself out there”, but they are woefully understating the case. But you will eventually learn the lesson. Just with a few broken bones. Like what, you ask? Well, as I explained to a suffering junior colleague, these things happen.
So, as an example of IoC, let’s take the Spring framework. Like other IoC frameworks, there are various ways to provide dependency injection: setters, constructors, and (in the case of Spring) annotations like @Autowired. Even though I’m not a fan of this modern magic, it’s fine, I get it: we’re trying to make things easier, as much I think it often does the opposite. And it works, so that’s what counts. However, as we will see, all of this magic swirls in a dense flog, obfuscating all apparent common sense.
So, Spring offers a slew of annotations, and if you use a caching layer like Redis, there is a handy one called @Cacheable. So, let’s say that you take advantage of it, and in the implementation of an @Autowired interface called DojoDataAccess, you create two methods that use the @Cacheable annotation:
@Cacheable("dojoData")
public List<DojoData> getDojoDataList(List<string> ids){
println("Cache is not being used");
for (String tmpId : ids) {
DojoData tmpData = this.getDojoData(tmpId);
}
...
}
@Cacheable("dojoData")
public List<DojoData> getDojoData(string id){
println("Cache is not being used");
...
}
So, if you call the “getDojoDataList()” function with a list of IDs (through an @Autowired instance), it’ll pull each “tmpId” from the cache, since the “getDojoData()” uses the cache…right?
Charlie Murphy is right: you would be wrong.
As it turns out, the @Cacheable is only invoked when it’s being addressed through the Autowired proxy interface. “But that should work!” Yes, IoC cadet, in the normal world, that should work…but you’re in the Upside Down, where things get only scarier when you turn a corner. So, how do ya fix that in a jiffy? Well, in the case of the obvious, you’re probably saying “Don’t do it”, being all judgy…but, yes, ugly things do work: an Autowired instance inside the very implementation that supports the original Autowired instance.
@Autowired
private DojoDataAccess dataAccess;
@Cacheable("dojoData")
public List<DojoData> getDojoDataList(List<string> ids){
println("Cache is being used");
for (String tmpId : ids) {
DojoData tmpData = dataAccess.getDojoData(tmpId);
}
...
}
@Cacheable("dojoData")
public List<DojoData> getDojoData(string id){
println("Cache is being used");
...
}
So, is that the recommended way to do things? No…but if you’re lazy and/or something needs to be fixed in the next five minutes, then it might be the right tool for the job.
But, more importantly, this kind of solution throws a wrench into all conventional thinking when it comes to programming. And this is the kind of thing that your average Joe or Joanna doesn’t even think about it while they’re walking down the road to IoC…until they step on a land mine like this one. And that’s when the broken bones come into play.
Or missing limbs, if you really need that cache to work right in your production environment.
So, remember: be careful out there.







