IoC is mostly a good thing within the Java language because when most applications start growing and you don't design for modularization/loose coupling, you end up with a big pile of interconnected classes without no sensible boundaries.
For starters, Spring and other IoC/DI frameworks makes you think about modularization right from the start. This is big because if you have your code well modularized/loose coupled, you end up componentizing and reusing much more wich leads to better unit testing (if you do unit testing anyway).
If I want to write a DAO, I can define its interface up front:
interface IPersonDao {
List<Person> getPersonsByTeam(String teamName);
}
then, I can just call for the implementation of this interface from anywhere in the src where's Spring is being "applied". Suppose i need it in a service layer:
class MyService {
@Autowired
IPersonDao svc;
}
or in a test class:
class TestPersonDao {
@Autowired
IPersonDao svc;
@Test
void testGetPersons(){
List<Person> persons = svc.getPersonsByTeam("billing");
Assert.assertDataSet(persons, "billing.xml");
}
}
Besides, my Dao implementation can hide the complexities of data access without messing with the Dao contract. If I require a hibernate session or a persistence manager, I just declare that:
class JpaPersonDao implements IPersonDao {
@PersistenceContext
EntityManager em;
List<Person> getPersonsByTeam(String tm) {
em.createQuery("...");
}
}
Componentization of classes requires a registry in order to wire collaborating beans. This could be developed by hand, but there are already DI frameworks that do this. Besides, Spring has alot of other stuff like exception translation, support for aspect programming, mvc frameworks, portlet frameworks, integration with hibernate, jpa and/or other db stacks which of course integrate nicely with the Spring IoC stuff.