Mike's Blog

Spring Certification: Container, Dependency and IOC | Reviewing the Study Guide

By: Micheal Arsenault

Posted: December 24, 2020| Modified: December 26, 2020

Reading Time: 7 minutes

Tags: certification Java Spring

resources:


The first section of the Study Guide is ‘Container, Dependency and IOC’ and I’m going to try and follow with that guided overview of material.

Container, Dependency and IOC

What is dependency injection and what are the advantages of using it?

To begin, let’s look at the ultimate source of human knowledge, Wikipedia!

In software engineering, dependency injection is a technique in which an object receives other objects that it depends on. These other objects are called dependencies. In the typical "using" relationship the receiving object is called a client and the passed (that is, "injected") object is called a service.

Wikipedia: Dependency_injection link icon

Basically here, instead of us calling the ‘new’ keyword in our code, we tell Spring that we need something and it will give it to us. This has numerous benefits that relate to better OO & SOLID principles:

  • Improves:
    • Testability because external dependencies can be more easily mocked or stubbed.
    • Clarity of the code because it’s responsibilities have been narrowed.
    • Cohesion of class’s interacting with each other as this design promotes coding by contract [Java Interfaces]
    • Maintenance as there is a clearer seperation of concerns the code is handling



What is an interface and what are the advantages of making use of them in Java?

...objects define their interaction with the outside world through the methods that they expose. Methods form the object's interface with the outside world;...

Oracle Java Documentation link icon

A Java interface let’s you expose just the functionality you’d like to expose to it’s users while hiding the more complicated implementation details. This also allows for different implementations to be used as well, preventing a lock-in of one implementation. So why does this matter? Again you can provide easier testing through mocks, as well as provide different levels of functionality by different implementations.




What is an ApplicationContext?

Central interface to provide configuration for an application. This is read-only while the application is running, but may be reloaded if the implementation supports this.

An ApplicationContext provides:

  • Bean factory methods for accessing application components. Inherited from ListableBeanFactory.
  • The ability to load file resources in a generic fashion. Inherited from the ResourceLoader interface.
  • The ability to publish events to registered listeners. Inherited from the ApplicationEventPublisher interface.
  • The ability to resolve messages, supporting internationalization. Inherited from the MessageSource interface.
  • Inheritance from a parent context. Definitions in a descendant context will always take priority. This means, for example, that a single parent context can be used by an entire web application, while each servlet has its own child context that is independent of that of any other servlet.

In addition to standard BeanFactory lifecycle capabilities, ApplicationContext implementations detect and invoke ApplicationContextAware beans as well as ResourceLoaderAware, ApplicationEventPublisherAware and MessageSourceAware beans.

Spring JavaDoc - Application Context link icon

OK! So we are finally getting to some Spring specific elements. At it’s core Spring is an Inversion of Control framework and it handles creating and instantiating the resources needed for your application. Spring will take in your Java as well as configuration metadata, this can be through @annotations that are applied throughout your java codebase, and provide you with fully instantiated objects ready to use throughout your application.

Source: Spring Core Doc




How are you going to create a new instance of an ApplicationContext?

In the below example you would provide Spring a set of classes that have Spring configuration metadata and from this you can pull out fully instantiated objects.

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);
    MyService myService = ctx.getBean(MyService.class);
    myService.doStuff();
}

Simple Construction Example

It should also be noted that you can instantiate a container and then provide metadata configuration after initial instantiation:

public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    ctx.register(AppConfig.class, OtherConfig.class);
    ctx.register(AdditionalConfig.class);
    ctx.refresh();
    MyService myService = ctx.getBean(MyService.class);
    myService.doStuff();
}

Source

This also ignores the creating of any Servlet Application Context containers!

Servlet Configuration

With Spring you can use the web.xml configuration

<web-app>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/app-context.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>app</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>

</web-app>

or the newer 3.0+ Servlet configuration

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { RootConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { App1Config.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/app1/*" };
    }
}

Also, while I’ve note mentioned any of the actual configuration metadata process, you have the option to have a package be scanned for Java classes that can be used; however, it’s important to note this is NOT A ZERO COST operation as scanning through large code bases will take time every time the application starts. Therefore, you should use scanning appropriately on code that would be picked up at least in a majority sense, and provide scoping or ignore rules to prevent unnecessary work.




Can you describe the lifecycle of a Spring Bean in an ApplicationContext?

Alright, this is a large and slightly tricky question, but it’s only tricky because there’s a lot of little steps that a bean will take in order to be fully prepared.

On a way zoomed back view, you can think of a bean being created like this: 1. Spring Container reviews configuration metadata and creates bean ‘recipes’ that will be instantiated later. 2. Spring processes additional configuration metadata that will affect how beans are created and additional capabilities, thereby altering the ‘recipe’ for beans. 3. Spring creates the beans providing resources of already created beans in order to fulfill dependencies. 4. Spring provides the ready made beans to be used 5. SHUTDOWN hooks inside the container object trigger shutdown operations that cascade custom

Now this is a way oversimplification of the process that actually occurs. I really recommend reviewing the actual documentation as there’s quite a few steps involved, and each step has a lot of detail.Spring core - beans-definition



You should also be aware of the differences in making changes to bean instances after they’re created and modifying the bean metadata ‘recipe’

BeanPostProcessor instances operate on bean (or object) instances. That is, the Spring IoC container instantiates a bean instance and then BeanPostProcessor instances do their work.

BeanPostProcessor instances are scoped per-container. This is relevant only if you use container hierarchies. If you define a BeanPostProcessor in one container, it post-processes only the beans in that container. In other words, beans that are defined in one container are not post-processed by a BeanPostProcessor defined in another container, even if both containers are part of the same hierarchy.

To change the actual bean definition (that is, the blueprint that defines the bean), you instead need to use a BeanFactoryPostProcessor, as described in Customizing Configuration Metadata with a BeanFactoryPostProcessor.

Bean Factory (i) info sectionlink icon



While this step is a very fundamental building block of the bean instantiation process, in a general sense it’s hidden from you in most cases except through interacting with either definition

https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-lifecycle

https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-extension-bpp



Here are some additional resources to review on this as it’s a rather spread out topic in the framework documentation: