1. Understanding of Spring IOC and AOP

IOC: Inverse of Control, the original process of manually creating objects is handed over to the Spring framework. You only need to inject objects when using them, and they can be used directly, simplifying the process of manually creating objects. At the same time, the dependency relationship and the whole life cycle of objects are separated. Handing over management to the Spring framework greatly reduces the complexity of development and maintenance of the project.

The IOC container itself is essentially a Map structure that holds object names and references between objects. In Spring, BeanFactory is the most common Spring IOC container interface, which defines IOC container-related methods.

DI: Dependency Injection. Spring manages the dependencies between one object and another. The Spring container will map the dependencies during object initialization.

AOP: AOP is the aspect programming, some common logic, can be abstracted into a aspect, reduce the intrusion of business logic, such as: log management, monitoring management, authority management and so on, reduce the coupling between modules and simplify repeated code. Spring AOP is based on dynamic proxy implementation. There are two approaches to dynamic proxy: JDK dynamic proxy and CGLIB dynamic proxy. Whether or not a proxy class implements an interface determines which approach to use.

2. Several ways of DI injectionHow beans are registered and injected

There are several common methods (some documents say: setter injection, constructor injection, interface injection, but interface injection is largely obsolete) :

1. Setter injection

Constructor injection

3. Field injection based on @autowired annotations

Both @Autowired and @Resource can be injected automatically. @Autowired is a Spring specification, and @Resource is a J2EE specification. Spring supports this annotation and makes it more powerful.

1. Different injection methods: @AutoWired can only provide byType injection. There is no other injection method. @Resource provides byName and byType. By default, byName is used for injection. You can use the name attribute to configure injection. If not, use byType for injection, which can be specified through the type attribute.

    @Resource(name = "add",type= Object.class)
Copy the code

2. @autoWired can be used on setters, fields, and constructors, but @resource cannot be used on constructors

Spring officially recommends using constructor injection. The disadvantage is that if too many parameters are injected, it will appear bloated. However, excessive parameters can be avoided through reasonable planning and decoupling to meet the principle of single responsibility.

1. You can ensure that dependencies are immutable and use final to decorate the variables to be injected

2. Dependencies are not null to avoid null pointer problems in field and setter injection

3, complete initialization, avoid cyclic dependence, in use, to ensure that is an initialization completed object.

See this article: Why constructor injection is recommended for Spring and the book Spring Unpacking

2. Scope of SpringBean

  • Singleton: Singleton, the default scope of Spring beans is singleton
  • Prototype: Generates a new instance each time
  • Session: Used on the Web, each session generates a new instance
  • Request: Used on the Web where a new instance is generated for each request
  • Global-session: Global session scope, only meaningful in portlet-based Web applications

Dynamic proxy and static proxy

Proxies are a design pattern that basically replaces all the functionality of one class with another and adds some variations of its own. Refer to the proxy pattern for details and usage

Static proxy: a compile-time enhanced proxy method in which the proxy-object and proxy-class are defined in the code, and the associated bytecode and class files are generated after compilation. The bytecode of the proxy-class is used directly at runtime

Dynamic proxy: Dynamic proxy is a run-time enhancement proxy that loads bytecode into the JVM. Dynamic proxy can be implemented in JDK dynamic proxy and CGLIB dynamic proxy.

Compared with dynamic proxy, static proxy has a more fixed structure and higher efficiency, but it is not flexible enough. In addition, a proxy class can only be used for one type of operations, but cannot be used for multiple operations. If multiple objects need to be proxy, multiple proxy classes need to be created.

JDK dynamic proxy

The core of JDK dynamic proxy is the InvocationHandler interface, which implements the interface proxy through reflection mechanism. In newProxyInstance, it will judge whether the proxied class implements the interface.

/** * To define an interface, the JDK dynamic Proxy must define the interface, because you can see proxy.class line 588
public interface Subject {
    void seeHello(a);
}

To use JDK dynamic proxies, you must implement an InvocationHandler class
public class SubjectInnvocationHandler implements InvocationHandler {
    private Object target;
    public SubjectInnvocationHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        method.invoke(target, args);
        return null; }}public class SubjectImpl implements Subject {
    @Override
    public void seeHello(a) {
        System.out.println("Han Meimei greets Li Lei"); }}public static void main(String[] args) {
    Subject proxy = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(),
    new Class[]{Subject.class}, new SubjectInnvocationHandler(new SubjectImpl()));
    // Call the methodproxy.seeHello(); } The essence of the JDK dynamic proxy is to add a new interface implementation to the proxy object, and then call it through reflection.Copy the code

CGLIB dynamic proxy

The CGLIB dynamic proxy, underneath, transforms bytecode and generates new classes using a small, fast bytecode processing framework ASM. The CGLIB proxy first implements a MethodInterceptor, and method calls are forwarded to the Intercept () method of that class.

public class HelloService { 
    public void sayHello(a) {
        System.out.println("HelloService:sayHello"); }}public class MyMethodInterceptor implements MethodInterceptor{
    /** * sub: cglib generated proxy object * method: proxied object method * objects: method entry * proxy: proxy method */
    @Override
    public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("====== Insert pre-notification ======");
        Object object = methodProxy.invokeSuper(sub, objects);
        System.out.println("====== insert the latter notification ======");
        returnobject; }}public static void main(String[] args) {
    // The process of obtaining proxy objects through CGLIB dynamic proxies
    Enhancer enhancer = new Enhancer();
    // Set the enhancer object's parent class
    enhancer.setSuperclass(HelloService.class);
    // Set the enhancer callback object
    enhancer.setCallback(new MyMethodInterceptor());
    // Create a proxy object
    HelloService proxy= (HelloService)enhancer.create();
    // Call the target method through the proxy object
    proxy.sayHello();
}
Copy the code

What is the difference between JDK dynamic proxies and CGLIB dynamic proxies

The JDK dynamic proxy is based on reflection. CGLIB is not based on reflection. Instead, it implements the proxy by creating a class that inherits from FastClass and calls methods directly from within.

2. The JDK dynamic proxy must require the proxy class to implement an interface. CGLIB does not require this because CGLIB is a subclass of the implemented propped class.

3. JDK dynamic proxies can proxy private and final classes, but CGLIB cannot proxy final or private or static classes or methods.

FastClass

The CGLIB dynamic proxy (CGLIB) is implemented using the FastClass implementation class. FastClass is implemented by generating an index value for each method of the proxy class based on the method name + parameter, etc. The index value can be used to locate the method to be requested and return the result of execution. You can see that in the last code


public class DelegateClass {
    private String type;
   
    public DelegateClass(a) {}public DelegateClass(String string) {
        this.type = string;
    }
    public boolean add(String string, int i) {
        System.out.println("This is add method: " + string + "," + i);
        return true;
    }
    public void update(a) {
        System.out.println("This is update method"); }}// FastClass dynamic subclass instance
FastClass fastClass = FastClass.create(DelegateClass.class);

// Create a delegate class instance
DelegateClass fastInstance = (DelegateClass) fastClass.newInstance(
    new Class[] {String.class}, new Object[]{"Jack"});

// Call the delegate class method, which returns the result
boolean result = (boolean)fastClass.invoke("add".new Class[]{ String.class, int.class}, 
fastInstance, new Object[]{ "Jack".25});

fastClass.invoke("update".new Class[]{}, fastInstance, new Object[]{});

Copy the code

FastClass is much simpler than reflection, especially for a class that does not implement an interface, it can also be proxy. You can refer to this article cglib source code analysis

Common definitions and 5 ways to advise in Spring AOP

Aspect: An Aspect, which can be understood as each AOP object defined, typically modified with the annotation @aspect

JoinPoint: every operation in the program execution process can be understood as a JoinPoint for each method of the class

Pointcuts are related to join points, which represent methods in a class. Pointcuts define rules that define which join points need to be entered into our cuts. The expression definition of a PointCut is to intercept a certain method, or a class of methods, or an annotation.

Advice: After matching pointcuts, Advice defines the order in which the aspect is executed, specifying the timing and logic when these JoinPoints are woven (or enhanced), and where the aspect code is actually executed. Currently, there are 5 ways to notify the section:

  1. Before: The pre-notification corresponds to @before
  2. After: The post-notification corresponds to @after
  3. Return: Returns a notification corresponding to @afterRETURNING
  4. Around: The surround notification corresponds to @
  5. Exception: Exception notification corresponds to @afterThrowing

The order of execution of these notifications:

Single section, normal execution

Single section, abnormal condition:

To explain step 4, when I use around myself, I usually use it like this:

log.info("[around] Pre notification");
Stopwatch stopwatch = Stopwatch.createStarted();
Object result = null;
try{
    joinPoint.proceed();
    cost = stopwatch.stop().elapsed(TimeUnit.MILLISECONDS);
}catch (Exception e){
    log.error("[around] exception notification",e);
}finally{
    log.info("[around] Surround rear notification");
}
Copy the code

If an exception occurs that is caught by a catch, AfterThrowing is not thrown. If it is not caught, AfterThrowing is thrown.

Multiple aspects, like a single aspect, are executed recursively, and the Order in which AOP is executed can be specified by Order.

The difference between BeanFactory and FactoryBean

BeanFactory is Spring’s top container interface. BeanFactory is a factory object for beans. It is used to generate and manage our own beans using a simple factory pattern. Generate the corresponding Bean object from the Bean format defined by the BeanDefinition.

A FactoryBean is itself a Bean object that can be used to generate complex Bean objects. FactoryBean provides a getObject method that can be overridden to generate arbitrary Bean objects. Factorybeans themselves use the factory method design pattern. If we want to define something that is different from SpringBean, such as redefining the scope, etc., You can use this FactoryBean to generate complex objects.

6,FactoryBeanandObjectFactory

ObjectFactory is similar to FactoryBeans in that both have a getObject method that creates objects, but FactoryBean creates Bean objects that are scoped by the Spring container, whereas ObjectFactory must manage the scope itself.

BeanFactory and ApplicationContext

BeanFactory is a top-level container interface. ApplicationContext is a subinterface of BeanFactory. ApplicationContext is more complex than BeanFactory.

  • Add the interface returned by multiple beans:BeanFactoryOnly one is provided by itselfBeanObject acquisition,ApplicationContextAccording toBeanThe name gets more than oneBeantheListSecondly, also inheritedHierarchicalBeanFactory, implement hierarchy or parent-child structure, etc.
  • Increase internationalization (MessageSource) : Added internationalization support
  • Multipathing Configuration (ResourceLoaderSupport) :ClassPath XmlandFileSystem XMLAnd other configuration modes.
  • Event Publishing mechanism (ApplicationEventPublisher) : Added event listening and event publishing.

9 Common Design patterns in Spring

  • Simple Factory model:BeanFactoryThis simple factory pattern, also known as the static factory pattern, is used to create objects
  • Factory Method:FactoryBeanThat’s the way it works
  • Proxy pattern: This is the most common; AOP, interceptors, and so on are usedJDK dynamic proxy or CGLIB dynamic proxy.
  • Observer mode: The observer mode is used for event publishing and listening
  • Policy mode: The policy mode is used in configuration file loading, which can be FileSystem loaded or Classpath loaded XML files.
  • Decorator mode: Generally withWrapper, such asBeanWrapperBoth use decorator patterns to enhance the properties of objects.
  • Adapter mode: inSpring MVCInside, more importantHandlerAdapterThe adaptor pattern is used to fit different typesHandler
  • Template method:RedisTemplate, jdbcTemplateIs this
  • Singleton: The most important singleton pattern, most common in Spring, is that beans are scoped singleton

All of the above are important to understand, but there are other patterns as well. For example, in Spring MVC, the Handler is assembled into a HandlerExecutionChain

  • Chain of Responsibility model

Life cycle of Spring Beans

  1. Instantiation: Bean init, implement reflection create object
  2. Initialization: populateBean implements the population of object attributes, using a level 3 cache
  3. Aware interface implementation: BeanAware interface check, such as BeanNameAware, BeanFactoryNameAware, etc., can be set properties
  4. BeanPostProcesser preprocessing: @PostConstruct is triggered when the preprocessor executes
  5. Execute the afterPropertiesSet method of InitializingBean
  6. Execute the init-method method
  7. Execute the BeanPostProcessor post method
  8. See if the relevant DisposableBean interface is implemented
  9. Execute the deStory method

Common extension points for Spring beans

  1. The use of various Aware interfaces, such as BeanNameAware, can be overwritten to BeanName
  2. BeanPostProcessor and BeanFactoryPostProcessor generate pre-processing and post-processing of beans and BeanFactory. BeanFactoryPostProcessor can do variable substitution. For example, placeholder substitution for DataSource and so on
  3. AOP proxies and @postConstruct initialization can be done in BeanPostProcessor
  4. AfterPropertiesSet and init-method can do initialization and so on

Are there threads in Spring?

The Spring framework itself is just a container, a container for managing beans, so the Spring framework itself does not have threads. Threads are generated by external Selvet containers such as Tomcat containers.

12. Are Spring beans thread safe

No, Spring beans are generally stateless, and if stateful, you need to avoid multithreaded concurrency safety issues. There are many solutions, such as common locks, lock-free cas, or using ThreadLocal for thread isolation.

Spring interceptors and filters

The filter

Take a look at the source code of Filter

package javax.servlet;

import java.io.IOException;
public interface Filter {
    The container calls init immediately after the Filter object is created, only once in its lifetime.
    // The filtering service cannot be provided until the init method is successfully executed.
    // The FilterConfig argument is used to get initialization parameters
    public void init(FilterConfig filterConfig) throws ServletException;
    FilterChain indicates the Filter chain. In the doFilter method, only the FilterChain method is executed.
    // to pass the request to the next Filter or Servlet for execution
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException;
    // Destruction method, called by the Web container when the service is removed. The destroy method is executed only once in its lifetime
    The //destroy method can be used to release held resources such as memory, file handles, and so on
    public void destroy(a);
}
Copy the code

The Filter is servlet-based, it’s called by the Servlet, so in Tomcat for example, the doFilter method is called in StandardWrapperValue, and then each doFilter method calls the next Filter.

The design pattern used by Filter is the chain of responsibility pattern, which is made through function calls.

Filter1->Filter2->Servlet->Filter2->Filter1 call, similar to recursion.

Filters can only be used in Web scenarios, single method calls are not available because they rely on Servlet calls to do encoding transformations, URL filtering, and so on

The interceptor

Interceptors are capabilities provided by the Spring framework that can do everything a filter can do, but are much more flexible than filters, and they can be implemented at the code level, called multiple times in a single request, or intercepted at the function level.

Filter->Servlet-> Interceptor 1 pre -> Interceptor 2 pre ->Controller-> Interceptor 2 post -> Interceptor 1 post ->Servlet->Filter

The implementation of the interceptor is based on the CGLIB dynamic proxy implementation, similar to the implementation of AOP, but in a different way.

14. Principle of Spring Boot automatic assembly

SpringBoot defines a set of interface specifications that state: When SpringBoot starts, it scans the meta-INF/Spring. factories files in the external reference JAR packages, loads the type information configured in the files into the Spring container, and performs various operations defined in the class. External jars can install their own functionality into SpringBoot only by following the standards defined by SpringBoot.

SpringBootApplication annotate it contains an important annotations EnableAutoConfiguration, this note there will be a key note, @ Import annotations can inject AutoConfigurationImportSelector, The selectImports method reads all the meta-INF/Spring. factories files with a key-value field in EnableAutoConfigure to identify the fully qualified class name of the object to be auto-assembled. Objects are loaded into the Spring Bean container through reflection; Meta-inf /spring-autoconfigure-metadata.properties defines loading conditions. This is a Java SPI mechanism, and dubbo is also an SPI mechanism at its core, although dubbo’s SPI is more flexible than SpringSPI.

Can refer to this article, written quite good Taobao side: “Talk about Spring Boot automatic assembly principle?

15. Spring level 3 Cache

Level 1 cache: singletonObject, which stores initialized singleton objects

Early exposed objects, semi-initialized objects, are generally stored in this

Tertiary caching: singletonFactories, factory objects for beans, used to create Bean proxy objects.

16. How does Spring solve the problem of loop dependency interlocking

Question 1: How does Spring solve the problem of loop dependencies

Spring does this by dividing the object initialization process into two parts: instantiation, which creates an empty object through reflection, and property population, which sets properties into the object through setter methods, using reflection. The problem of cyclic dependencies is solved by splitting the initialization process into two parts and then adding a level 3 cache. In fact, if you want to achieve an important part of the loop dependency is to achieve the property of the filling and object generation, not at the same time, lazy loading can also solve the problem of the loop dependency.

Question 2: Why level 3 caches to solve loop dependencies, and why not level 2 caches

  1. Why can’t level 1 cache be implemented?

If there is only one level cache, then the early exposure and the already initialized object will be in the same object, so there may be multiple threads access, not the initialized one, there will be a null pointer, so the first level cache will not work.

  1. Why not just two levels of caching?

L1, on the basis of a certain can realize, two levels of cache must also can to some extent, but why is the Spring with the l3 cache, the main problem is that when have AOP agent, there are some is to use is not a proxy object, part of using the proxy object, this is wrong.

  1. If you use two levels of caching, and the proxy objects are exposed manually in advance, isn’t that ok?

It’s not self-evident, but it’s theoretically possible, if you manually expose proxy objects in advance and remove the tertiary cache, in fact it’s possible, but using proxy objects is much less likely than using a direct loop dependency, if you remove the tertiary cache, Each object needs to go through the process of exposing proxy objects in advance, which is relatively inefficient.

Question 3: In what scenarios can circular dependencies not be resolved?

Spring solves Setter injection, singleton mode loop dependency problem, prototype mode and constructor injection method, can not solve the problem, and the reason is easy to understand, prototype mode generates new object every time, can not determine whether the object exists. This will throw an exception BeanCurrentlyInCreationException, constructor injection, instantiate and initialize must be completed at the same time, therefore cannot solve circular dependencies, as not all dependency injection way is constructor injection way, also can use the constructor injection to the solution of circular dependencies.

Note: Spring creates beans in A natural order by default, so A creates them before B

How does Spring solve circular dependencies? And interview essentials, talk about loop dependencies in Spring

17. Isolation level of transactions in Spring

The isolation level of each transaction is the same as the isolation level of the database. ISOLATION_READ_UNCOMMITTED: Reads are not committed. Data that is not committed can be read. This solves the problem of update loss, but dirty read data, phantom read data, and unrepeatable read data are easily generated. ISOLATION_READ_COMMITTED: Allows reading of data already committed by concurrent transactions. Dirty reads can be prevented, but phantom or unrepeatable reads can still occur ISOLATION_REPEATABLE_READ: The result of multiple reads of the same field is the same, unless the data is modified by the transaction itself, which can prevent dirty reads and unrepeatable reads. However, phantom reads can still occur. In MySQL, next-key lock and gap lock can solve phantom problems to some extent. ISOLATION_SERIALIZABLE: Highest isolation level, fully subject to ACID isolation level. All transactions are executed one by one so that interference between transactions is completely impossible. That is, this level prevents dirty reads, unrepeatable reads, and phantom reads. But this severely affects the performance of the program. This level is also not typically used.

Note: The isolation level of a transaction can be set by Spring itself. If the isolation level set by Spring is different from the isolation level set by the database, the isolation level set by Spring will prevail. Of course, the premise is that the isolation level set by Spring is supported by the database.

18. Transaction management in Spring

Programmatic transaction and declarative transaction two kinds, general programming use little, most are direct use declarative transaction.

19. Transaction propagation in Spring

  • PROPAGATION_REQUIRED: Joins the current transaction if it exists, creates a new transaction if it does not exist.
  • PROPAGATION_REQUIRED_NEWIf a transaction exists, the transaction is suspended and a new transaction is created.
  • PROPAGATION_SUPPORTS: If a transaction exists, it is added to the current transaction. If it is not supported, it is executed in a non-transactional manner.
  • PROPAGATION_NOT_SUPPORTED: Suspends the transaction if it exists and runs in a non-transactional manner.
  • PROPAGATION_MANDATORY: runs as a transaction, throwing an exception if no transaction exists.
  • PROPAGATION_NEVER: Runs nontransactionally and throws an exception if a transaction currently exists.
  • PROPAGATION_NESTED: Creates a transaction to run as a nested transaction of the current transaction if one exists; If there is no transaction, the value is equivalent toTransactionDefinition.PROPAGATION_REQUIRED.

For a concrete example, you can see this article, which is very well written: Spring Transactions

20. Causes of Spring transaction failure

This can be understood in conjunction with this AOP proxy:

  1. The underlying database engine does not support transactions and only InnoDB can use transactions
  2. Without injecting beans into the Spring container, beans cannot be container-managed and therefore cannot use proxies.
  3. Internal calls are invalid because AOP proxies use the this pointer instead of Spring proxies.
  4. An exception occurs, but the exception is caught and not thrown, in which case the external transaction cannot be rolled back.
  5. The exception is thrown, but no rollback exception is set. The default is RuntimeException. You can set the type of exception to be caught with the rollFor parameter.
  6. Methods that use transactions are not public and cannot be propped. Protected and package cannot perform transactions. Static and final cannot perform transactions because CGLIB propped requires a subclass that can be overridden.

21, Spring MVC URL access process

SpringMVC execution flow:

  1. The user sends a request to the front-end controllerDispatcherServlet
  2. DispatcherServletA request is received to invoke the processor mapperHandlerMapping.
  3. The processor mapper finds the specific processor based on the request URL and generates the processor execution chainHandlerExecutionChainBoth the processor object and the processor interceptorDispatcherServlet.
  4. DispatcherServletPer processorHandlerGet processor adapterHandlerAdapterperformHandlerAdapterHandle a series of operations, such as: parameter encapsulation, data format conversion, data validation, etc
  5. Execution processorHandler(Controller, also known as page controller).
  6. HandlerReturn after executionModelAndView
  7. HandlerAdapterwillHandlerThe execution resultModelAndViewReturn to theDispatcherServlet
  8. DispatcherServletwillModelAndViewTo pass toViewResloverView parser
  9. ViewResloverReturns concrete after parsingView
  10. DispatcherServletrightViewRender the view (that is, model datamodelFill to view).
  11. DispatcherServletRespond to the user.

22. Nine components in Spring MVC

Spring MVC (DispatchServlet Javadoc)

  • HandlerMapping: processor mapper that looks for handlers based on the user’s request URL.
  • HandlerAdapter: Adapter. Handler may have a variety of processor, we commonly used is @ RequestMapping this, this is based on the annotation RequestMappingHandlerAdapter, another is the way to realize the Controller interface, Corresponding adapter for SimpleControllerHandlerAdapter, can rewrite the Controller inside the handleRequest method of the interface, to implement the processor, and the third is SimpleServletHandlerAdapter, Used to handle requests for servlets.
  • HandlerExceptionResolver: Handling exceptions
  • ViewResolver: View parser, this is actually used a little bit less now, now is usually front end separation, generally do not use this view parser.
  • RequestToViewNameTranslator: specifies that no return value is returned
  • LocaleResolver: Internationalization conversion
  • ThemeResolverTheme:
  • MultipartResolver: File upload
  • FlashMapManager(Sweat) No, I haven’t

HandlerMapping, HandlerAdapter, and MultipartResolver are the core components of HandlerMapping, HandlerAdapter, and MultipartResolver.

conclusion

During this period of time, I have read some spring-related documents and source code. So far, I have sorted out 22 questions, all of which are common interview questions. I will continue to update this document in the future to help me record the knowledge related to Spring, and also to discuss some interview questions in Spring with my friends. You can leave a comment below on the interview questions you met. I hope I can help you. If you have any questions, PLEASE give me some advice. Thank you.