Tuesday, November 30, 2021

Spring Professional Certificate Study Guide Section 1-1, Question 1-15

1.1 Container, Dependency and IOC

In this article, I'm going to answer the first 15 questions of Section 1.1 from the Professinal VMware Spring Certificate study guide. Those questions are:
  1. What is dependency injection and what are the advantages of using it? 
  2. What is an interface and what are the advantages of making use of them in Java? 
  3. What is an ApplicationContext?
  4. How are you going to create a new instance of an ApplicationContext?
  5. Can you describe the lifecycle of a Spring Bean in an ApplicationContext?
  6. How are you going to create an ApplicationContext in an integration test?
  7. What is the preferred way to close an application context? Does Spring Boot do this for you?
  8. Are beans lazily or eagerly instantiated by default? How do you alter this behavior?
  9. What is a property source? How would you use @PropertySource?
  10. What is a BeanFactoryPostProcessor and what is it used for? When is it invoked?
  11. What is a BeanPostProcessor and how is it different to a BeanFactoryPostProcessor? What do they do? When are they called?
  12. What does component-scanningdo?
  13. What is the behavior of the annotation @Autowired with regards to field injection, constructor injection and method injection? 
  14. How does the @Qualifier annotation complement the use of @Autowired? 
  15. What is a proxy object and what are the two different types of proxies Spring can create?

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

Dependency Injection: A design pattern widely used in e.g. Spring Framework and CDI (Contexts and Dependency Injection) since Java EE 6.0. 
DI can be viewed as a special case of IOC(Inversion of Control).

Motivation

If Class A uses a method/variable in Class B, we say class A has a dependency on Class B.

Now let's say we want to get an attribute(intimacyPercentage) of Class Dog from Class Person. The easiest way to do it is:

	//Person has a dependency on PetDog
	public class Person{
		Dog myDog = new Dog();
		protected int myPetIntimacyPercentage() {
			return myDog.getIntimacyPercentage();
		}
	}
	
	public class Dog{
		protected int intimacyPercentage = 5;
		protected int getIntimacyPercentage () {
			return intimacyPercentage;
		}
	}

Since the class Person has dependency on the class Dog, if we change the getIntimayPercentage method in Dog class, class Person has to be recompiled as well.
That's when we should use DI (Dependency Injection) to inject the dependencies only later instead of initializing the dependencies inside the class.

Let's say we want to replace Dog with another class DogV2. There are following ways to do DI:

1. Setter Injection: (Not recommended)
public class PersonWithSetterInjection {
		Dog myDog;
		
		void setMyDog (Dog d) {
			myDog = d;
		}
		
		protected int myPetIntimacyPercentage() {
			return myDog.getIntimacyPercentage();
		}
	}

By removing "new" keyword, we remove the class Person's responsibility to create a dog instance. The dog instance can be created from the outside and assigned later to Person now. Even injecting a subclass of Dog, for example Chihuahua, is now possible.
A drawback of this approach is that if you forget to call setMyDog method, a method invokation of myPetIntimacyPercentage will cause run-time error. 

2. Constructor Injection: ( Use this!)
We can move the assignment of myDog=d into a constructor, so the compiler will tell us if  d is null and myPetIntimacyPercentage is called.

Advantages: Easier to test, immutable dependency object, help us think about class design and prevent god object anti-pattern.

3. Field Injection: (Not recommended)


Conclusion on DI

To sum up, the concept behind DI is "inversion of control", which states the dependencies should not be configured statically inside a class, but rather dynamically by some other class. (from the outside)

When should I use DI? Consider using DI pattern whenever the code expects a future extension (this often depends on the lifespan of the code and the engineers knowledge to the application).


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

  1. Using interfaces allows classes to have functionalities that might not logically belong to them. Can be used to describe optional attributes. For example, some weapons in a first-person shooter game could be sold to NPCs, while same could not. This is a characteristic of a weapon that doesn't logically belong to it and an interface sellable with same associated methods such as sell() could be of good use.
  2. Advantages of using interfaces: 
    • quasi-multiple inheritance
    • achieves abstraction
    • achieves loose coupling: If we change class A, we won't have to change class B, because the dependency is loose.


  • 3. What is an ApplicationContext? What are Beans?

BeanFactory: An interface that represents the IoC Spring container that instantiates, configures, and manages a number of beans and is usually used by Spring development team. 

ApplicationContext: An interface that implements the BeanFactory interface with enhanced, enterprise-specific functionalities. Provides configuration for an application.
Common implementation classes:
1. AnnotationConfigApplicationContext: Load ApplicationContext from annotations

2. ClassPathXmlApplicationContext: Load ApplicationContext from xml configuration files using class paths

3. FileSystemXmlApplicationContext:  Load ApplicationContext from xml configuration files (either in local file system or URLs) Use "file:" prefix will enforce an absolute path.

Bean: All objects that are instantiated, assembled and managed by the Spring Container. We should only configure following specific types of objects to be beans:
    Service layer objects, data access objects (DAOs), presentation objects such as Struts Action instances, infrastructure objects such as Hibernate SessionFactories, JMS Queues, and so forth.

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

ApplicationContext context = 
new AnnotationConfigApplicationContext(DemoConfig.class);
In DemoConfig.java:

 package com.mypackage.demo;  
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration @EnableAspectJAutoProxy @ComponentScan("com.mypackage.demo") public class DemoConfig { }
  • 5. Can you describe the lifecycle of a Spring Bean in an ApplicationContext?
Interface BeanDefinition: describes a bean instance and contains following metadata:
    • package-qualified actual implementation class of the bean
    • Scope, Lifecycle callbacks
    • References to other beans needed for this bean to work 
Scopes of BeanDefinition Instances
There are 6 predefined scope, while a custom scope is also possible.
    a. @singleton: only one instance will ever be created
    b. @prototype: new instances upon request for that bean
The following 4 scopes are only available if you are using a web-aware ApplicationContext (i.e. a class implementing the WebApplicationContext interface)
    c. @RequestScope: A new Bean instance is created for each HTTP request
    d. @SessionScope: A new Bean instance is created for each HTTP session
    e. @ApplicationScopeA new Bean instance is created for the entire web application, it is similar to singleton but it is a singleton per ServletContext, not per ApplicationContext.
    f. websocket:  

Lifecycle of Spring Beans:
Source: https://howtodoinjava.com/spring-core/spring-bean-life-cycle/

Elaboration:
§ Container startup , config. xml loaded
-> Method postProcessBeanFactory() method from BeanFactoryPostProcesser interface invoked 
-> getBean() 
-> postProcessBeforeInstantiation() method from Interface InstantiationAwareBeanPostProcessor invoked 
-> Instantiation 
-> postProcessAfterInstantiation() method from InstantiationAwareBeanPostProcessor invoked
-> postProcessPropertyValues() method from 
InstantiationAwareBeanPostProcessor invoked.

-> populate properties

§ setApplicationContext() is invoked after setBeanFactory().


  • 6. How are you going to create an ApplicationContext in an integration test?
Integration test:
Test that covers either 1. multiple units, 2. multiple layers or 3. whole path through the application. It can be performed without deployment to server. The correct wiring of Beans and data access using JDBC or ORM tool can be tested. (including SQL, Hibernate queries, JPA mapping, etc)

-> In Spring framework, this is enabled by both
1. the org.springframework:spring-test module and the 
@ContextConfiguration annotation.

2. JUnit module

A JUnit4 Runner is class that extends JUnit's abstract Runner class and should be set using the @RunWith annotation so it can run test to a class:
 @RunWith(MyTestRunner.class)  
 public class MyTestClass {  
 @Test  
 public void myTest() {  
 ..  
 }  
 }  

In JUnit 4: 
The Runner class implements the Describable interfaces, which contains information collected during test and can be exported as test reports later. Runner has two abstract methods: getDescription() and run(). BlockJUnit4ClassRunner is the default runner if not otherwise specified.

JUnit 5: 
JUnit 5 = JUnit Platform (API for IDEs, build tools and console) + JUnit Jupiter (annotation-based API & test engine) + JUnit Vintage (test engine for JUnit3&4 tests to ensure backward compatibility)


-> In Spring boot (Spring Boot application is a spring ApplicationContext), use @SpringBootTest annotation

https://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/html/boot-features-testing.html

  • 7. What is the preferred way to close an application context? Does Spring Boot do this for you?

1. For standalone non-web applications: Use close().
(This will also destroy all beans in its BeanFactory)

 ((ConfigurableApplicationContext)applicationContext).close();  
Alternatively: This register a SpringContextShutdownHook with JVM, and the ApplicationContext will be closed on JVM shutdown.

((ConfigurableApplicationContext)applicationContext).registerShutdownHook();

2. For web applications:
Context will be closed automatically by the ContextLoadListener.

3. Spring Boot:
All contexts will be closed automatically!

  • 8. Are beans lazily or eagerly instantiated by default? How do you alter this behavior? 

It depends on the Bean scope.
Singleton: Eager instantiated, which means the bean instance is created at application startup. 
Prototype: Lazily instantiated, which means instances are created upon requests.

Advantages of Lazy initialization:
Reduce startup time by spreading CPU load over time (esp. important in Docker and Kubernetes platforms)

Autowiring Collaborators:
 public class BaseballCoach implements Coach{  
      @Autowired  
      @Qualifier("myStudentListN")  
      private List<Student> myStudents;  
      ...
}

@Autowired
Beans can be autowired to other beans so we don't have to specify properties or constructor arguments.

@Qualifier ("<BeanName>")

To change the behavior for all Beans: 

 @ComponentScan(lazyInit = true)  
 @Configuration  
 public class ApplicationConfiguration{  
 }  
or for single Bean with @Component, @Configuration, @Bean annotation:

 
 @Lazy(true)
...

Note: Package org.springframework.stereotype:

Usages:
1. For correct component scanning (to make good use of IoC Container)
2. Draw nice AOP Point-cut Boundaries 

Five Sub-Types:
1. @Component: generic @Interface found by automatic component scanning. Basically one can use this annotation for all Bean detection needs. The following four are @Component with specialized usages.

2. @Controller
Concept : Spring MVC Architecture:
# Spring DispatcherServlet the is a front controller, which forwards requests to handler mapper, which then forwards request to mapped controller.
# The Controller invokes business logic behind the scene, and send response back to DispatcherServlet.
# The DispatcherServlet then send reposnse to be rendered to the resolver(view template), where the results are presented.

The above mentioned paradigm is applicable to MVC Controllers as well as RestControllers. (RESTful apps are service-oriented and return raw data (e.g. JSON). Since no rendering is needed, there is no ViewTemplate in collaboration with @RestController.
 @RestController  
 @RequestMapping("/api")  
 public class CustomerRestController {  
      @Autowired  
      private CustomerService customerService;  
      @GetMapping("/customers")  
      public List<Customer> getCustomers(){  
           return customerService.getCustomers();  
      }  
      @GetMapping("/customers/{customerId}")  
      public Customer getCustomer(@PathVariable int customerId){  
           Customer theCustomer = customerService.getCustomer(customerId);  
           if(theCustomer == null) {  
                throw new CustomerNotFoundException("Customer id not found - "+customerId);  
           }  
           return theCustomer;  
      }  



https://www.baeldung.com/spring-controllers

Allows us to auto-detect implementation classes through classpath scanning.
 @Controller  
 @RequestMapping("/crypto")  
 public class CryptoController {  
      @Autowired  
      private CryptoService cryptoService;  
      @Value("#{txTypeOptions}")  
      private Map<String, String> txTypeOptions;  
      @Value("#{exchangeOptions}")  
      private Map<String, String> exchangeOptions;  
      @GetMapping("/list")  
      public String listTransactions(Model theModel) {  
           List<CryptoTransaction> theTransactions = cryptoService.getTransactions();  
           theModel.addAttribute("transactions", theTransactions);  
           calculate(theTransactions);  
           theModel.addAttribute("coins", transactionToCoin.getOwnedCoins());  
           return "list-transactions";  
      }  
 }  

3. @Indexed:

4. @Repository:
Similar to DAO(Data Access Object) pattern in that they both should provide CRUD operations on database. However, DAO pattern is low-level and table-centric, where repository is object-oriented.

5. @Service:
Wrapper for business logic.

6. @Bean: When @Component doesn't work (e.g. if we don't have access to the source code, @Component won't work) 
 @Bean  
 public BeanExample beanExample() {  
   return new BeanExample();  
 }  
Differences to @Component:
1. @Bean is used at method level.
2. @Bean has to be manually instantiated, not auto-detected like @Component.
3. Therefore, @Bean decouples the Bean instantiation from its class definition. So multiple Bean definitions or implementation from external libraries are possible.  


  • 9. What is a property source? How would you use @PropertySource? How to use PropertySourcesPlaceholderConfigurer? 

ApplicationContext has an implementation of the Environment interface. An Environment has two key aspects:
1. profiles: A group of Beans to be registered if the profile is active. (@Profile)
2. properties: Property files, JVM system props, sys. env. props, JNDI props, etc.
Properties are a key-value pairs, represented in Spring as implementations of the abstract class PropertySource

 @Configuration  
 @EnableWebMvc  
 @EnableTransactionManagement  
 @ComponentScan("com.luv2code.springdemo")  
 @PropertySource({ "classpath:persistence-mysql.properties" })  
 public class DemoAppConfig implements WebMvcConfigurer {  
      @Autowired  
      private Environment env;  
      private Logger logger = Logger.getLogger(getClass().getName());  
      // define a bean for ViewResolver  
      @Bean  
      public DataSource myDataSource() {  }  
      private int getIntProperty(String propName) {
		
		String propVal = env.getProperty(propName);
		
		// now convert to int
		int intPropVal = Integer.parseInt(propVal);
		
		return intPropVal;
	}	
  }  

Then we can access the loaded properties using @Value(${<propertyName>}) or env.getProperty(<propertyName>) 


§ What is PropertySourcesPlaceholderConfigurer?
Class PropertySourcesPlaceholderConfigurer extends class 
PlaceholderConfigurerSupport. It resolves ${...} placeholders in Bean property value definitions against Environment and its PropertySources.


  • 10. What is a BeanFactoryPostProcessor and what is it used for? When is it invoked? 

See question 5: Bean lifecycle.

Interface BeanFactoryPostProcessor can modify the bean metadata (scope, properties, etc.) before its instantiation. 

Interface BeanPostProcessor: Applies customized logic before and/or after the init-method (Of course, after Bean Instantiation)

  • 11. What is a BeanPostProcessor and how is it different to a BeanFactoryPostProcessor? What do they do? When are they called? 

See Question 10.

  • 12. What does component-scanning do?

Spring scans classpath to search classes annotated with stereotypes and create Beans based on those definitions.
 @ComponentScan(  
  basePacakges= "xxx.yyy.zzz",  //where to search for Beans
  includeFilters = @ComponentScan.Filter(type= FilterType.xxx, pattern = ".*Beans"  
 )  
 public class ApplicationConfiguration{  
 }  

  • 13. What is the behavior of the annotation @Autowired with regards to field injection, constructor injection and method injection?

The class AutowiredAnnotationBeanPostProcessor is a special BeanPostProcessor that processes @Autowired annotation. 

By default, all autowiring @Autowired attributes are mandatory, but we can set this to optional by writing @Autowired(required = false).

@Order, @Priority -> specify the sorting order of Beans or Components in a collection.

How does @Autowired find the correct class definitions?
1. Match by type, if not found -> step 2
2. If multiple beans of same type found -> If @Primary exists, inject that bean. Done.
3. Check if @Qualifier(<BeanName>) exists for field.
4. Match by Bean name
5. throw exception (NoSuchBeanDefinitionException, NoUniqueBeanDefinitionException)


@Autowired fields, constructors and methods can have any visibility level.
  • fields: Create Bean -> Injection -> Init.
  • constructors: If there is only one constructor, then no need to annotate @Autowired.
  • methods: for multiple parameters, then all parameters are required by default.


  • 14. How does the @Qualifier annotation complement the use of @Autowired? 

Read Question 13



  • 15. What is a proxy object and what are the two different types of proxies Spring can create?

According to microsoft website, the purpose of the proxy object is to monitor the life span of the accessible object and to forward calls to the accessible object only if it is not destroyed. It adds additional code on top of object being proxied without having to modify the logic of the proxied object (this enables AOP!). Proxy objects provide same public methods as the proxied objects. It is used to implement aspects contracts for AOP(Aspect-oriented Programming)  

Disadvantages of proxies and AOP:
1. Code is harder to debug
2. Needs to be documented additionally for development collaboration
3. Performance issues 


Spring provides two kinds of proxies:
1. JDK Dynamic Proxy: Used by default, if target object (object to be proxied) implements at least one interface. Only interface methods will be proxied.

2. CGLIB Proxy: If the target object doesn't implement any interface. 
Note that final methods cannot be advised for CGLIB proxies, since they cannot be overridden by subclasses.
To force the use of CGLIB, you need to write:

 <aop:config proxy-target-class="true">  
   <!-- other beans defined here... -->  
 </aop:config>  

No comments:

Post a Comment