×
Community Blog Interview Questions We've Learned Over the Years: Spring

Interview Questions We've Learned Over the Years: Spring

This article is part of a series focusing on interview questions for technicians, with a specific emphasis on Spring.

By Taosu

1

Design Concepts & Beans

1. IoC: Inverse of Control

IoC (Inverse of Control) is a design concept where the control originally exercised within a program to manually create objects is delegated to a framework like Spring. In other languages, IoC is also applied and is not unique to Spring.

An IoC container is the carrier of Spring to implement IoC. IoC container is actually a Map (key, value) that stores various objects. The dependencies between objects are given to the IoC container to manage, and the IoC container completes the injection of objects. This can greatly simplify the applications' development and free the applications from complex dependencies. An IoC container acts like a factory, and when we need to create an object, we only need to configure the configuration files and annotations, and we don't need to consider how the objects are created.

DI: Dependency Injection

From the perspective of a container, DI (Dependency Injection) refers to the process of injecting other objects that one object depends on during its creation into the object.

2. AOP Dynamic Proxy

AOP (Aspect-Oriented Programming) enables encapsulation of logic and responsibilities that are unrelated to the core businesses but commonly called across business modules, including transaction processing, log management, and access control. This reduces the duplication of code in the system, decreases the coupling between modules, and facilitates future scalability and maintainability.

Spring AOP operates based on the dynamic proxy. If the target object implements an interface, Spring AOP will utilize JDKProxy to create a proxy object. However, if the object does not implement any interface, it cannot use JDK Proxy to be proxied. In this case, Spring AOP will resort to Cglib dynamic proxy, which is built on ASM framework byte stream. When this occurs, Spring AOP will use Cglib to generate a subclass of the target object to serve as the proxy.

3. Bean Lifecycle

Singleton

Summary: The lifecycle of a singleton object is the same as that of a container.

Prototype

Birth: Spring framework creates the object for us when we use objects

Alive: The object is alive as long as it is in use

Death: When an object is not used for a long time and no other objects are referenced, it is recycled by Java's garbage collection mechanism

2

The IoC container initialization process which loads Bean:

@Overridepublic void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) {  // Step 1: Pre-processing before refreshing   prepareRefresh();  //Step 2: Get BeanFactory and register it with BeanDefitionRegistry  ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();  // Step 3: Preparation for loading BeanFactory (BeanFactory makes some settings, such as the class loader of context.)  prepareBeanFactory(beanFactory);  try {    // Step 4: Post-preparation work after completing the preliminary setup of the BeanFactory     postProcessBeanFactory(beanFactory);    // Step 5: Instantiate BeanFactoryPostProcessor interface Bean     invokeBeanFactoryPostProcessors(beanFactory);    // Step 6: Register the BeanPostProcessor. After the bean is created, execute     registerBeanPostProcessors(beanFactory);    // Step 7:Initialize the MessageSource component (for internationalization, message binding, message parsing);     initMessageSource();    // Step 8: Register the initialization event dispatcher     initApplicationEventMulticaster();    // Step 9: Override this method in subclasses to customize the logic when the container is refreshed      onRefresh();    // Step 10:Register the listener of the application. That is, register and implement the listener interfaced by ApplicationListener    registerListeners();    //Step 11: Initialize all remaining non-lazy loading singleton beans. Initialize and create a non-lazy loading singleton Bean instance (no attribute set)    finishBeanFactoryInitialization(beanFactory);    //Step 12: Complete context refresh. It is mainly to call the onRefresh() method of the LifecycleProcessor to complete the creation of finishRefresh(); }...}

Summary:

Four Stages

  • Instantiation
  • Populate
  • Initialization
  • Destruction

Multiple Extension Points

  • Affecting multiple Beans

    • BeanPostProcessor
    • InstantiationAwareBeanPostProcessor
  • Affecting a single Bean

    • Aware

Complete Process

  1. Instantiate a bean — that's the new that we often say.
  2. Configure the instantiated Bean according to the Spring context, that is, IoC injection;
  3. If the Bean has implemented the BeanNameAware interface, it will call its setBeanName(String) method, that is, according to the Bean ID and name in the Spring configuration file.
  4. If the Bean has implemented the BeanFactoryAware interface, it will call setBeanFactory(BeanFactory), that is, the Spring factory configured by the Spring configuration file to pass the Spring factory itself.
  5. If the Bean has implemented the ApplicationContextAware interface, it will call the setApplicationContext(ApplicationContext) method, which is the same as the information passed by 4. However, since the ApplicationContext is a BeanFactory sub-interface, it is more flexible.
  6. If the Bean is associated with the BeanPostProcessor interface, it will call the postProcessBeforeInitialization() method. BeanPostProcessor is often used as a Bean content change. Since this method is called at the end of Bean initialization, it can also be applied to memory or caching technology.
  7. If the Bean is configured with init-method properties in the Spring configuration file, its configured initialization method is automatically called.
  8. If the Bean is associated with the BeanPostProcessor interface, it will call postProcessAfterInitialization() to print logs or three-level cache technology bean upgrade;
  9. After the above work is completed, this Bean can be applied. Then this Bean is a Singleton, so in general, when we call a Bean with the same ID, we are calling the instance with the same content and address. Of course, non-Singleton can also be configured in the Spring configuration file, which we will not introduce too much here.
  10. When the Bean is no longer needed, it will go through the cleanup stage. If the Bean implements the DisposableBean interface or calls the implemented destroy() method according to the destroy-method attribute of the spring configuration

4. Bean Scope

Name Scope
singleton Singleton object, the default value scope
prototype Each fetch creates a new Bean instance
request Each HTTP request results in a new Bean that is valid only within the current HTTP request
session In one HTTP session, the container will return the same instance
global-session Store the object in the session domain of the web project cluster. If no cluster exists, the global session is equivalent to the session

The default scope is Singleton. When multi-thread accessing the same Bean, there will be thread security risks.

Methods to Guarantee Thread Safety:

  1. Avoid defining mutable member variables in bean objects (unrealistic).
  2. Define a ThreadLocal member variable in classes and store the required variable in ThreadLocal.

ThreadLocal:

Each thread has its own ThreadLocalMap class object, which can keep the thread's objects in it. Each thread can correctly access its own objects.

Take a common ThreadLocal static instance as the key, save the references of different objects to the ThreadLocalMap of different threads, and then obtain the object saved by one's own thread through the get() method of this static ThreadLocal instance everywhere the thread executes, thus avoiding the trouble of passing this object as a parameter.

5. Circular Dependency

Circular dependency is actually a circular reference, that is, two or more Beans hold each other and eventually form a closed loop. For example, A depends on B, and B depends on A. Circular dependencies in Spring include:

  • Prototype Bean circular dependency
  • Circular dependency of the constructor (constructor injection)
  • Circular dependency of Field property (set injection)

Among them, the circular dependency problem of the constructor cannot be solved. When solving the circular dependency of properties, lazy loading can be used, and Spring uses the method of exposing objects in advance.

Lazy loading @Lazy to solve the circular dependency problem

When Spring starts, it will parse and convert all bean information (including XML and annotations) into BeanDefinition that Spring can recognize and store it in Hashmap for the following initialization, and then process each BeanDefinition. The initialization of ordinary Beans is performed during the container startup initialization phase, while the bean decorated by lazy-init=true is triggered when context.getBean() is triggered from the container for the first time.

Level-3 cache to solve the circular dependency problem

3

  1. To initialize ClassA, the Spring container uses the constructor to initialize the objects before the exposure to the Spring container singletonFactorys (level-3 cache).
  2. When ClassA calls the setClassB method, Spring first attempts to obtain ClassB from the container. At this point, ClassB does not exist in the Spring container.
  3. The Spring container initializes ClassB. ClasssB first exposes itself in the level-3 cache and then obtains ClassA from the level-1, level-2, and level-3 cache of the Spring container.
  4. After you obtain ClassA, you instantiate the instance and add the instance to the singleton pool. Then, the instance ClassA obtains ClassB from the Spring container and initializes the instance.
  5. In this way, both ClassA and ClassB complete object initialization, which solves the problem of circular dependencies.

Spring Annotations

1. @SpringBoot

Annotations for the declaration of Beans

@Component: general-purpose annotations. You can label any class as a Spring component.

@Service: used at the business logic layer (service layer)

@Repository: used at the data access layer (dao layer)

@Controller: used at the presentation layer, the declaration of the controller (controller layer)

Annotations for injecting Beans

@Autowired: assemble and inject by type by default.

@Qualifier: You can change to name

@Resource: assemble and inject by name by default. JDK annotations have been deprecated in the new version.

@Autowired Annotation Principle

The use of @Autowired simplifies our development.

It implements AutowiredAnnotationBeanPostProcessor class. This class implements the Spring framework's extended interfaces.

It implements BeanFactoryAware interface to hold its internal BeanFactory (so we can easily get the dependent Bean).

It implements the MergedBeanDefinitionPostProcessor interface, instantiates the Bean before getting the @Autowired information, and caches it.

It implements the postProcessPropertyValues interface, instantiates the Bean, and retrieves the annotation information from the cache. Through reflection, dependent objects are set into the properties of the Bean.

@SpringBootApplication

@SpringBootApplicationpublic class JpaApplication {    public static void main(String[] args) {        SpringApplication.run(JpaApplication.class, args);    }}

@SpringBootApplication annotation is equivalent to the following three annotations:

  • @SpringBootConfiguration: the underlying layer is Configuration annotation. To put it bluntly, it supports the JavaConfig way to configure it.
  • @EnableAutoConfiguration: enable the automatic configuration feature
  • @ComponentScan: the scan annotation. By default, the package of the current class is scanned.

Among the above, @EnableAutoConfiguration is the key (enable automatic configuration). The inside actually loads the information of the META-INF/spring.factories file, filters out the data with EnableAutoConfiguration as the key, and loads it into the IoC container to realize the automatic configuration feature!

It mainly loads the @SpringBootApplication annotation main configuration class. The main feature of this @SpringBootApplication annotation main configuration class is that SpringBoot opens an automatic configuration feature of @ EnableAutoConfiguration annotation.

The Role of @EnableAutoConfiguration:

It mainly uses the EnableAutoConfigurationImportSelector to import some components into the Spring container.

@Import(EnableAutoConfigurationImportSelector.class)public @interface EnableAutoConfiguration

2. @SpringMVC

@Controller declares that this class is a Controller in SpringMVC. @RequestMapping is used to map web requests. @ResponseBody supports placing the return value in the response instead of a page. Usually, the user returns JSON data. @RequestBodyallows the parameters of the request to be in the request body instead of directly connecting after the address. @PathVariable is used to receive the path declared by the path parameter. @RequestMapping("/hello/{name}") and put the annotation before the parameter to obtain the value, which is usually used as the interface implementation method of the Restful. 

SpringMVC Principle

4

  1. The client (browser) sends the request directly to the DispatcherServlet.
  2. The DispatcherServlet calls HandlerMapping based on the request information to parse the request handler.
  3. After parsing to the corresponding Handler (that is, the Controller), it starts to be processed by the HandlerAdapter adapter.
  4. The HandlerAdapter calls the real processor based on the Handler to process requests and process the corresponding business logic.
  5. After the processor processes the business, a ModelAndView object is returned. The Model is the returned data object.
  6. The ViewResolver finds the actual View based on the logic View.
  7. The DispaterServlet passes the returned Model to the View (View rendering).
  8. Return the View to the requester (browser)

3. @SpringMybatis

@Insert: insert SQL. The syntax is the same as XML insert SQL. @Select : query SQL. The syntax is the same as XML select SQL. @Update : update SQL. The syntax is the same as XML update SQL. @Delete : delete SQL. The syntax is the same as XML delete SQL. @Param: input parameters @Results: set the result set @Result: the result @ResultMap: reference result set @SelectKey: get the latest insert ID 

How does MyBatis prevent SQL injection?

Simply put, #{} is precompiled and safe.

**{} is not precompiled and just takes the value of the variable, so it is not safe and can involve SQL injection. When you write mapping statements for MyBatis, try to use the format **"#{xxx} "**. If you need to dynamically pass in the table name and column name, you also need to make the following modifications: add the attribute **statementType="STATEMENT"**, and change the value of all variables in SQL to ****{} without precompilation. It only takes the value of the variable, which is unsafe and involves SQL injection. When you write mapping statements for MyBatis, try to use the format **"#{xxx} "**. If you need to dynamically pass in the table name and column name, you also need to make the following modifications: add the attribute **statementType="STATEMENT"**, and change the values of all variables in SQL to **{xxxx}**

Difference between MyBatis and Hibernate

Hibernate Framework:

Hibernate is an open-source object-relational mapping framework, which provides a very lightweight object encapsulation for JDBC to map objects to database tables. is a fully automated, fully object-oriented persistent layer framework.

MyBatis framework:

MyBatis is an open-source object-relational mapping framework, formerly known as iBATIS, which was renamed after Google took over in 2010. It is a semi-automated persistent layer framework.

Differences:

Development:

During the project development process, in terms of speed:

In Hibernate development, SQL statements have been encapsulated and can be used directly to speed up system development.

MyBatis is semi-automated, and SQL needs to be completed manually, which is a little cumbersome.

However, nothing is absolute. In the context of massive and complex system projects where complex statements abound, Hibernate may not be the ideal solution.

SQL Optimization:

Hibernate automatically generates SQL, and some statements are more cumbersome, which consume more performance.

MyBatis needs manual writing of SQL, which can avoid unnecessary queries and improve system performance.

Object Management:

Hibernate is a complete object-relational mapping framework. During the development process, you do not need to focus on the underlying implementation details, but rather, you can concentrate on managing objects.

MyBatis needs you to manage mappings by yourself.

4. @Transactional

@EnableTransactionManagement @Transactional

Notes:

① Do not process time-consuming tasks in transaction functions, which will result in long-term possession of database connections.

② Do not process irrelevant business in the transaction functions to prevent transaction rollback due to exceptions.

Transaction propagation properties:

  1. REQUIRED (default property) supports the current existing transaction if one transaction exists. If no transaction exists, a new transaction is started.
  2. MANDATORY supports the current transaction. If there is no current transaction, an exception is thrown.
  3. NEVER executes in a non-transactional manner and throws an exception if a transaction currently exists.
  4. NOT_SUPPORTED executes operations in a non-transactional manner. If a transaction currently exists, it is suspended.
  5. REQUIRES_NEW creates a new transaction. If a transaction currently exists, it is suspended.
  6. SUPPORTS supports the current transaction. If no transaction exists, the transaction is executed in non-transactional mode.
  7. NESTED supports partial rollback of the current transaction. Savepoints are added to commit or roll back the current transaction. A very important concept of nested transactions is that the inner transaction depends on the outer transaction. If the outer transaction fails, the actions of the inner transaction are rolled back. Conversely, the failure of the inner transaction operation does not cause the rollback of the outer transaction.

Spring Source Code Reading

Design Patterns in Spring

Singleton design pattern: Beans in Spring are singleton by default.

Factory design pattern: Spring uses the factory pattern to create Bean objects through BeanFactory and ApplicationContext.

Proxy design pattern: The implementation of Spring AOP.

Observer pattern: The Spring event-driven model is one classic application of observer pattern.

Adapter pattern: The enhancement or notification (Advice) of Spring AOP uses the adapter pattern. Spring MVC also uses adapter pattern to adapt to Controller.


Disclaimer: The views expressed herein are for reference only and don't necessarily represent the official views of Alibaba Cloud.

0 1 0
Share on

Alibaba Cloud Community

1,062 posts | 262 followers

You may also like

Comments