Summary of knowledge system (8) SSM framework system

Article Directory

Spring-based

1-1. The difference between Spring, SpringMVC, Mybatis and SpringBoot

  • Spring is a lightweight Java enterprise-level development framework that provides many functions and features, such as:
    • Inversion of Control (IOC)
    • Dependency Injection (DI)
    • Aspect Oriented Programming (AOP)
    • Spring transaction management
  • Spring MVC is a part of the Spring framework, focusing on the development of web applications, providing the following functions:
    • receive request
    • Set request interceptor
    • response data
    • global exception handling
  • Mybatis is a data persistence layer framework . When dealing with databases, you can use simple XML or annotations to configure and map the original information in database tables, and complete the mapping between Java entity classes in the system and records in the database .
  • Spring Boot is a framework that simplifies the development of Spring applications. Through starting dependencies and automatic configuration , it greatly simplifies the process of spring configuration, allowing developers to focus more on the implementation of business logic.

insert image description here

1-2. Commonly used annotations and functions in Spring

  1. Configuration Bean related:
  • @Autowire: Let the Spring container automatically assemble Bean into the class.
  • @ComponentScan: Discover and register components that meet the conditions through an automatic scanning mechanism.
  • @Configuration: Used to specify configuration classes, replacing traditional XML configuration files.
  • @Bean: Used to declare the Bean definition in the @Configuration class for Spring container management.
  • @Qualifier: Used together with @Autowired to resolve the ambiguity of autowiring by specifying the Bean name.
  • @Value: Used to inject simple values ​​or expressions into Bean properties.
  • @Scope: Used to specify the scope of the Bean, such as a singleton (Singleton) or prototype (Prototype).
  • @ConfigurationProperties: It is used to bind the properties in the configuration file to the fields of the Java class, and supports batch binding.
  1. SpringMVC related:
  • @Component: General annotation, indicating that this class should be managed by Spring. Use this annotation if a bean does not know which layer it belongs to.
  • @RequestMapping: The processing method used to map HTTP requests to controllers, for example: @RequestMapping("/books")
  • @PathVariable: Used to get URL path variable values ​​and map to method parameters.
    // 处理URL: /books/{id}
    @GetMapping("/{id}")
    public String getBookById(@PathVariable Long id) {
    
    
        // 处理方法逻辑
        return "book_details";
    }
  • @RequestParam: Used to get the value of the request parameter and map it to the method parameter.
    // 处理URL: /books?category=fiction
    @GetMapping
    public String getBooksByCategory(@RequestParam("category") String category) {
    
    
        // 使用category进行业务逻辑处理
        // ...
        return "books_by_category";
    }
  • @ResponseBody: Used to return the method return value directly as the content of the HTTP response.
@RestController
@RequestMapping("/api")
public class BookController {
    
    

    @PostMapping("/books")
    public ResponseEntity<String> createBook(@RequestBody Book book) {
    
    
        // 处理从请求体中解析出来的 Book 对象
        // ...
        return new ResponseEntity<>("Book created successfully", HttpStatus.CREATED);
    }
}
  • @Controller: Control layer annotations, process HTTP requests and return responses. There is also the @RestController annotation, which is a collection of @Controller and @ResponseBody.
  • @Service: Used to identify the service layer class, usually used to annotate Service components.
  • @Repository: Used to identify data access layer classes, usually used to annotate DAO components.
  • @Transactional: Used to identify transaction methods and enable method-level transaction management.

1-3. What design patterns are used in the Spring framework?

  1. Factory mode: Bean objects are created using BeanFactory or ApplicationContext in Spring. The factory pattern hides the construction details from the customer, and only needs the customer to provide product parameters, that is, returns the product object to the customer.
  2. Singleton mode: The default scope of Bean in Spring is singleton (singleton). In Spring, the singleton mode is implemented in a special way to implement the singleton registry through ConcurrentHashMap. The advantage of using the singleton mode is that for frequently used objects, the time spent creating objects can be omitted, system overhead can be reduced, and GC pressure can be reduced.
  3. Proxy mode: Spring AOP is implemented based on dynamic proxy. Proxy objects implement enhanced business logic. If the object to be enhanced implements the interface, use JDK dynamic agent to realize it. If the object to be enhanced does not implement the interface, use CGlib dynamic proxy.
  4. Template Method: The Template Method pattern is a behavioral design pattern that defines the skeleton of an algorithm in an operation while deferring some steps to subclasses. The template method enables subclasses to redefine the implementation of some specific steps of the algorithm without changing the structure of the algorithm. A large number of template methods are used in the Spring framework, such as HibernateTemplate and other classes that end with Template to operate on the database. JdbcTemplate,
  5. Listener mode: Spring event release-monitoring is applied to the listener mode, but when an event occurs, the listener judges whether it is the object it is listening to, so as to decide whether to execute the listening callback.
  6. Adapter mode: In Spring AOP, there are many types of notifications, such as pre-, post-, wrap-around, before-destruction, and exceptions. All non-wraparound notifications need to call AdvisorAdapter to convert to wraparound notifications, and then hand them over to the method interceptor (MethodInterceptor ).
  7. Responsibility chain mode: An object in Spring AOP is configured with multiple notifications, which is executed according to the responsibility chain mode. In the chain of responsibility model, each node can choose to process the task or hand it over to the next node directly. Similar to this are interceptors in SpringMVC and filters in JDK.

Spring IoC 、 DI、Bean

2-1. What is Spring IoC, what are its benefits, and how is it implemented in Spring?

IoC (Inversion of Control: Inversion of Control) is a design idea, which is to hand over the control of objects created manually in the program to the Spring framework for management, that is, to hand over the power of object creation and management to the Spring container.

The interdependence between objects is managed by the IoC container, and the object injection is completed by the IoC container. The IoC container is like a factory. When we need to create an object, we only need to configure the configuration file/= or annotation, without considering how the object is created. Simplify application development and use layered decoupling.

insert image description here

In Spring, the IoC container is the carrier used by Spring to implement IoC. The IoC container is actually a Map (key, value) registry. The Map stores various Bean objects, and the key is the name (or ID) of the Bean. value is the definition information of Bean, including class name, dependency relationship, initialization method, destruction method, etc.

2-2. What are the annotations for declaring Bean?

In simple terms, Bean refers to the objects managed by the IoC container.

Bean configuration can be configured through XML files, or it can be set through annotations. for example:

  • @Component: A general annotation that can mark any class as a Spring component. If a Bean does not know which layer it belongs to, it can be marked with * @Component annotation.
  • @Controller : Corresponding to the Spring MVC control layer, it is mainly used to accept user requests and call the Service layer to return data to the front-end page.
  • @Service : Corresponding to the service layer, which mainly involves some complex logic and requires the use of the Dao layer.
  • @Repository (warehouse): Corresponds to the persistence layer, namely the Dao layer, which is mainly used for database-related operations.

2-3. What is the difference between @Component and @Bean?

  1. The @Component annotation acts on classes, while the @Bean annotation acts on methods.
  2. @Component is usually automatically detected and automatically assembled into the Spring container through class path scanning (we can use the @ComponentScan annotation to define the path to be scanned to find out the class that needs to be assembled and automatically assemble it into the Spring bean container). The @Bean annotation usually means that we define and generate this bean in the method marked with the annotation. @Bean tells Spring that this is an instance of a certain class, and it will be returned to me when I need to use it.
  3. The @Bean annotation is more customizable than the @Component annotation, and in many places we can only register beans through the @Bean annotation. For example, when we refer to classes in third-party libraries that need to be assembled into the Spring container, it can only be achieved through @Bean.

2-4. What are the annotations for injecting beans, and what is the difference between @Autowired and @Resource?

Both Spring's built-in @Autowired and JDK's built-in @Resource and @Inject can be used to inject beans.

  • @Autowired is an annotation provided by Spring, and @Resource is an annotation provided by JDK. The default injection method of Autowired is byType (matching according to type),
  • The default injection method of @Resource is byName (matching based on name).

When there are multiple implementation classes for an interface, both @Autowired and @Resource need to match the corresponding Bean correctly by name.

  • @Autowired can explicitly specify the name through the @Qualifier annotation
  • @Resource can explicitly specify the name through the name attribute.

For example, the SmsService interface has two implementation classes: SmsServiceImpl1 and SmsServiceImpl2, and both of them have been managed by the Spring container.

// 报错,byName 和 byType 都无法匹配到 bean
@Autowired
private SmsService smsService;
// 正确注入 SmsServiceImpl1 对象对应的 bean
@Autowired
private SmsService smsServiceImpl1;
// 正确注入  SmsServiceImpl1 对象对应的 bean
// smsServiceImpl1 就是我们上面所说的名称
@Autowired
@Qualifier(value = "smsServiceImpl1")
private SmsService smsService;


// 报错,byName 和 byType 都无法匹配到 bean
@Resource
private SmsService smsService;
// 正确注入 SmsServiceImpl1 对象对应的 bean
@Resource
private SmsService smsServiceImpl1;
// 正确注入 SmsServiceImpl1 对象对应的 bean(比较推荐这种方式)
@Resource(name = "smsServiceImpl1")
private SmsService smsService;

2-5. Is the Bean thread-safe?

Whether a bean in the Spring framework is thread-safe depends on its scope and state.

Under the scope of multiple instances (prototype), a new bean instance is created every time it is acquired, so there is no resource competition problem, so there is no thread safety problem.

Under the scope of singleton (singleton) , the IoC container has only one bean instance, and there may be resource competition problems. If the bean has state and contains variable member variables, then there is a thread safety problem.

For thread safety issues that are stateful and singleton beans, there are two common solutions:

  1. Try to avoid defining mutable member variables in Bean
  2. Define ThreadLocal in the class, and save the required member variables in TheadLoacl to make the thread private.

2-6. What is the life cycle of Bean?

  1. The IoC container finds the definition of Spring Bean in the configuration file
  2. The IoC container uses Java reflection to create an instance of a Bean
  3. If the attribute assignment of some Bean is involved, such as using the @Value annotation, use the set() method to set the attribute value.
  4. If the Bean implements the BeanNameAware interface, call the setBeanName method and pass in the name of the Bean.Aware接口是在编译阶段内置在Bean中,用来与IoC容器打交道,获取Bean的相关信息时用的。4 - 7 都是一些Aware接口,了解Aware接口的概念即可,不用记得那么细致。
  5. If the Bean implements the BeanClassLoaderAware interface, call the setBeanClassLoader() method and pass in the instance of the ClassLoader object.
  6. If the Bean implements the BeanFactoryAware interface, call the setBeanFactory() method and pass in the instance of the BeanFactory object.
  7. If other *.Aware interfaces are implemented, the corresponding methods are called.
  8. If there is a BeanPostProcessor object associated with the Spring container that loaded this bean, execute the postProcessBeforeInitialization() method.即初始化前的Bean后处理器
  9. If the Bean implements the InitializingBean interface, execute the afterPropertiesSet() method.InitializingBean是与Aware类似 的接口,是与Bean耦合的,InitializingBean接口会执行初始化逻辑
  10. If the definition of the Bean in the configuration file contains the init-method attribute, the method specified by init-method will be executed.8 - 10 是Bean初始化时可以设置的三种回调,它们的顺序分别是 Bean初始化前的后处理器、InitializingBean内置接口、配置属性init - method
  11. If there is a BeanPostProcessor object related to the Spring container that loads this bean, execute the postProcessAfterInitialization() method即销毁前的Bean后处理器
  12. If the Bean implements the DisposableBean interface, execute the destroy() method.DisposableBean 接口是与InitializingBean类似的耦合接口
  13. If the Bean definition in the configuration file contains the destroy-method attribute, execute the specified method.11-13是与初始化时相对应的,在销毁前的3种回调,它们的执行顺序与初始化是一样的,即 后处理器 、耦合接口、配置属性

The life cycle of the Bean listed above is a bit too long:
simple to remember:

The main context of the Bean life cycle includes:

  • 1. Bean configuration
  • 2. Bean instantiation
  • 3. Bean initialization
  • 5. The use of beans
  • 4. Bean destruction

Expanded to include:

  • 1. Find the Bean definition in the configuration file
  • 2. Instantiate beans based on reflection
  • 3. If the Bean implements the Aware-related coupling interface, execute the corresponding implementation method
  • 4. Bean initialization:
    • Bean post-processor: pre-processing
    • Coupling interface: InitializingBean
    • Bean configuration properties: the method specified by init-method
    • Bean post-processor: post-processing
  • 5. The use of beans
  • 6. Bean destruction:
    • Bean post-processor: destruction pre-processing
    • Coupling interface: DisposableBean
    • Bean configuration property: the method specified by destroy-method
      insert image description here

2-7. How does Spring solve the circular dependency problem?

There are three forms of circular dependencies:

  1. Interdependence, that is, A depends on B, and B depends on A, forming a circular dependency between them.
  2. Indirect dependencies, that is, A depends on B, B depends on C, and C depends on A, forming a circular dependency.
  3. Self-dependence, also A depends on A to form a circular dependency.

Spring has designed a three-level cache to solve the circular dependency problem. The first-level cache stores complete and available Bean instances. After the second-level cache stores instantiated Bean instances that have not yet set attribute values, that is, the dependency injection in the Bean has not been processed. The first-level cache is used to store the Bean factory. It is mainly used to generate the original Bean object and put it into the second-level cache . The core idea of ​​the third-level cache is to separate the dependency injection of the bean from the instantiation of the bean. The cache caches fully available instances, uses the second-level cache to cache instances that have not been filled with attributes, and exposes the instances that have not been filled with attributes in advance.

For example : a certain field or setter of A depends on the instance object of B, and at the same time a certain field or setter of B depends on the instance object of A” such a circular dependency situation.

  • A first completes the first step of initialization (createBeanINstance instantiation), and exposes itself to singletonFactories in advance.
  • At this time, in the second step of initialization, I found that I depended on object B. At this time, I tried to get(B), and found that B had not been created, so I went through the create process. B found that I depended on the object during the first step of initialization. A, so try get(A), try the first-level cache singletonObjects (definitely not, because A has not been fully initialized), try the second-level cache earlySingletonObjects (nor), try the third-level cache singletonFactories, because A exposes itself in advance through ObjectFactory So B can get the A object through ObjectFactory.getObject (although A has not been fully initialized, but it is better than nothing). Put it into the first-level cache singletonObjects by yourself.
  • Returning to A at this time, A can get the object of B and successfully completes its own initialization phases 2 and 3. Finally, A also completes the initialization and enters the first-level cache singletonObjects, and more fortunately, because B got The object reference of A, so the A object that B now holds has completed the initialization.

Spring AoP

AOP (Aspect-Oriented Programming: Aspect-Oriented Programming) can encapsulate the logic or responsibility (for example , etc.) that has nothing to do with business but is commonly called by business modules, so as to reduce the duplication of code in the system and reduce the coupling between modules. And it is conducive to future scalability and maintainability.事务处理、日志管理、权限控制

3-1. How is Spring AoP implemented?

Spring AoP is implemented based on dynamic proxy, and its implementation methods are divided into:

  • 1. JDK-based dynamic proxy: For the target object that implements the interface, Spring uses JDK dynamic proxy to create the proxy object. JDK dynamic proxy is implemented through Java's native Proxy class. The proxy object implements the target interface, and adds enhanced logic to the invoke method of InvocationHandler. The original method is implemented based on reflection, method.invoke('object to be enhanced', 'method parameter');

    • The specific implementation principle:
      • 1. The proxy object must implement the InvocationHandler interface. JDK inherits the Proxy class when implementing it, provides the construction method of InvocationHandler, and passes super to InvocationHandler during execution.
      • 2. Use Proxy.newProxyInstance to generate a proxy object. The proxy object is a dynamically generated bytecode based on ASM (bytecode manipulation framework) technology, so it needs to be passed to the class loader to load the bytecode into an object.
      • 3. The acquisition of the interface method is obtained through reflection, that is, calling the getMethod method from the bytecode of the class. In order to avoid the overhead of multiple call getMethod, the proxy object uses static members to save the method, and through the static code The block is initialized with a value.
      • 4. In order to handle methods with return values, the return value in the proxy object is an Object object. The capture and processing of exceptions in the method are divided into runtime exceptions and checked exceptions. Runtime exceptions are thrown directly, and checked exceptions are wrapped as UndeclaredThrowableException and then thrown.
      • 5. jdk reflection optimization, when the interface method is enhanced, the reflection method is used to call the method, so the performance is lossy, and jdk internally optimizes this. When the number of calls reaches the 17th time, jdk will generate an internal The proxy object of the method, directly call the method of the proxy object instead of calling in the form of reflection.
  • 2. Dynamic proxy based on CGLib: CGLib dynamic proxy adopts the method of inheritance + method interceptor to enhance the inheritable target class.

    • The specific implementation principle:
      • 1. Generate proxy class: When the target class needs to be proxied, CGLIB will generate a proxy class at runtime, which inherits from the target class and becomes a subclass of the target class.
      • 2. Interceptor: In CGLIB, the logic of the proxy is implemented by an interceptor (MethodInterceptor), which is responsible for executing additional logic before and after the method call of the proxy class. The interceptor is similar to the InvocationHandler in the JDK dynamic proxy.
      • 3. Redirection of method calls: When the method of the proxy class is called, CGLIB will redirect the method call to the intercept() method of the interceptor. In the intercept() method, the enhanced logic to the target method can be implemented and the target method can be called.
      • 4. Proxy object creation: Through the bytecode generation technology, CGLIB converts the definition of the proxy class into bytecode, and uses ClassLoader to load the bytecode, and finally generates the proxy object.

3-2. The implementation difference between CGLIB and JDK dynamic proxy

  1. Principle and implementation method:
    JDK dynamic proxy: JDK dynamic proxy is realized through Java native java.lang.reflect.Proxy class and InvocationHandler interface. At runtime, the JDK dynamic proxy generates the proxy object of the target interface, and implements the interception and enhancement of the target method through the invoke() method of InvocationHandler.
    CGLIB dynamic proxy: CGLIB dynamic proxy uses the CGLIB library and bytecode generation technology to generate a subclass of the target class as a proxy class at runtime. In the subclass, CGLIB realizes the interception and enhancement of the target method by generating the MethodProxy object.

  2. Proxy type:
    JDK dynamic proxy: JDK dynamic proxy can only proxy the target class that implements the interface. If the target class does not implement any interface, it cannot be proxied using JDK dynamic proxy.
    CGLIB dynamic proxy: CGLIB dynamic proxy can proxy the target class that does not implement the interface. It implements the proxy by generating subclasses of the target class, so it can also proxy for classes without interfaces.

  3. Performance:
    JDK dynamic proxy: When JDK dynamic proxy calls the proxy method, it involves reflection calls, which has a certain performance overhead. The proxy efficiency is relatively low, especially when there are many proxy methods, the performance drop is more obvious.
    CGLIB dynamic proxy: When CGLIB dynamic proxy calls the proxy method, it directly calls the method of the generated subclass without reflection call, so it has higher performance than JDK dynamic proxy. It is especially suitable for situations where there are many proxy methods or proxy objects are created frequently.

  4. Dependency and compatibility:
    JDK dynamic proxy: JDK dynamic proxy depends on Java's native java.lang.reflect.Proxy class, which has good compatibility with the Java platform and does not need to introduce additional third-party libraries.
    CGLIB dynamic proxy: CGLIB dynamic proxy depends on the CGLIB library, and the corresponding dependencies need to be introduced when using it. CGLIB dynamic proxies work well on the Java platform, but there may be compatibility issues on other Java virtual machines (JVMs).

3-3. What is the difference between Spring AOP and AspectJ AOP?

  • Spring AOP is a runtime enhancement, while AspectJ is a compile-time enhancement.
    Spring AOP is based on proxying (Proxying), while AspectJ is based on bytecode manipulation (Bytecode Manipulation). Spring AOP has integrated AspectJ, and AspectJ should be regarded as the most complete AOP framework in the Java ecosystem. AspectJ is more powerful than Spring AOP, but Spring AOP is relatively simpler. If we have fewer aspects, there is little difference in performance between the two. However, when there are too many aspects, it is best to choose AspectJ, which is much faster than Spring AOP.

Spring MVC

4-1 What are the core components of SpringMVC?

  • DispacherServlet: The core central processor, responsible for receiving, distributing and responding to client requests.
  • HandlerMapping: The processor mapper matches the URL to find the Handler that can be processed, and encapsulates the interceptor involved in the request with the Handler.
  • HandlerAdapter: Processor adapter, according to the handler found by HandlerMapping, adapt to execute the corresponding Handler
  • Handler: request processor
  • ViewResolver: The view resolver, according to the view/logical view returned by the Handler, parses and renders the real view, and passes it to the DispatcherServlet to respond to the client.

4-2 How does SpringMVC work?

insert image description here
Process description (important):

  1. The client (browser) sends a request, and DispatcherServlet intercepts the request.
  2. DispatcherServlet calls HandlerMapping based on request information. HandlerMapping matches and finds the Handler that can be processed according to the uri (that is, what we usually call the Controller controller), and encapsulates the interceptor involved in the request with the Handler.
  3. DispatcherServlet calls the HandlerAdapter adapter to execute the Handler.
  4. After the Handler finishes processing the user request, it will return a ModelAndView object to the DispatcherServlet. ModelAndView, as the name suggests, contains information about the data model and the corresponding view. Model is the returned data object, and View is a logical View.
  5. ViewResolver will find the actual View based on the logical View.
  6. DispaterServlet passes the returned Model to View (view rendering).
  7. Return the View to the requester (browser)

4-3 How to do SpringMVC unified/global exception handling?

Unified exception handling using @ControllerAdvice + @ExceptionHandler annotations.

@ControllerAdvice is the controller enhancement, which is used to handle the exception handling logic of the control layer, while other layers (Service, Dao) only need to continuously throw out exceptions, without considering the exception handling code.

@ExceptionHandler: You can specify the type of exception to be intercepted. Generally, we can divide it into runtime exceptions and custom exceptions.

@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
    
    

    @ExceptionHandler(BaseException.class)
    public ResponseEntity<?> handleAppException(BaseException ex, HttpServletRequest request) {
    
    
      //......
    }

    @ExceptionHandler(value = ResourceNotFoundException.class)
    public ResponseEntity<ErrorReponse> handleResourceNotFoundException(ResourceNotFoundException ex, HttpServletRequest request) {
    
    
      //......
    }
}

In this exception handling method, exception handling logic (AOP) will be woven into all or specified Controllers. When a method in the Controller throws an exception, it will be handled by the method modified by the @ExceptionHandler annotation.

The getMappedMethod method in ExceptionHandlerMethodResolver determines which method is modified by the @ExceptionHandler annotation to handle the exception.

@Nullable
	private Method getMappedMethod(Class<? extends Throwable> exceptionType) {
    
    
		List<Class<? extends Throwable>> matches = new ArrayList<>();
    //找到可以处理的所有异常信息。mappedMethods 中存放了异常和处理异常的方法的对应关系
		for (Class<? extends Throwable> mappedException : this.mappedMethods.keySet()) {
    
    
			if (mappedException.isAssignableFrom(exceptionType)) {
    
    
				matches.add(mappedException);
			}
		}
    // 不为空说明有方法处理异常
		if (!matches.isEmpty()) {
    
    
      // 按照匹配程度从小到大排序
			matches.sort(new ExceptionDepthComparator(exceptionType));
      // 返回处理异常的方法
			return this.mappedMethods.get(matches.get(0));
		}
		else {
    
    
			return null;
		}
	}

It can be seen from the source code: getMappedMethod() will first find all the method information that can match exception handling, then sort them from small to large, and finally take the smallest matching method (that is, the one with the highest matching degree).

4-4 What is the difference between an interceptor and a filter?

insert image description here
The Filter interface requires us to rewrite three methods:

init: initialization, execute only once
doFilter: call after intercepting the request, it can be called multiple times, here you can release the request by executing chain.doFilter().
destroy: The destruction method is called only once.
insert image description here
insert image description here

  1. In terms of dependencies, interceptors belong to the SpringMVC framework, while filters belong to the Servlet system.
  2. In terms of specific use, the interface specifications of the two are different. The filter needs to implement the Filter interface, and the filter execution has three stages: init(), doFilter(), and destroy(). The interceptor needs to implement the HandleInterceptor interface, which also has three stages: preHandler(), postHandler() and afterCompletion().
  3. In terms of execution sequence: all requests are first intercepted by the filter chain Filter, and after release, the request is distributed by DispatcherServlet and enters the interceptor chain. A smooth request, the stages it goes through are:过滤器1 拦截前 -> 过滤器2 拦截前 …… Servlet分发器-> 拦截器1拦截前 -> 拦截器2 拦截前 …… 最后的拦截器 拦截后 ……->第一个拦截器 -> Servlet分发器 -> 最后的过滤器 拦截后 ……->第一个过滤器
  4. In terms of function: filters are mainly used to filter and process requests and responses, such as character encoding processing, illegal request filtering, and response encryption. Interceptors are mainly used to implement some functions related to business logic, such as identity authentication, permission verification, logging, performance monitoring, etc.
public void init(FilterConfig filterConfig) throws ServletException;

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;

public void destroy();

boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception;

void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception;

Spring transaction

programmatic transaction management

Programmatic transaction management: manually manage transactions through TransactionTemplate or TransactionManager.

The sample code for programmatic transaction management using TransactionTemplate is as follows:

@Autowired
private TransactionTemplate transactionTemplate;
public void testTransaction() {
    
    

        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
    
    
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
    
    

                try {
    
    

                    // ....  业务代码
                } catch (Exception e){
    
    
                    //回滚
                    transactionStatus.setRollbackOnly();
                }

            }
        });
}

The sample code for programmatic transaction management using TransactionManager is as follows:

@Autowired
private PlatformTransactionManager transactionManager;

public void testTransaction() {
    
    

  TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
          try {
    
    
               // ....  业务代码
              transactionManager.commit(status);
          } catch (Exception e) {
    
    
              transactionManager.rollback(status);
          }
}

Declarative transaction management

Use the annotation @Transactional to achieve through AOP:

@Transactional(propagation = Propagation.REQUIRED)
public void aMethod {
    
    
	  //do something
	  B b = new B();
	  C c = new C();
	  b.bMethod();
	  c.cMethod();
}

5-1 How many ways does Spring manage affairs?

  • Programmatic transactions: hardcoded in the code (not recommended): manually manage transactions through TransactionTemplate or TransactionManager, which is rarely used in practical applications, but it is helpful for you to understand the principles of Spring transaction management.
  • Declarative transactions: configured in XML configuration files or directly based on annotations (recommended): actually implemented through AOP (full annotations based on @Transactional are used most)

5-2 What kinds of transaction propagation behaviors are there in Spring transactions?

The transaction propagation behavior is to solve the transaction problem of calling each other between the business layer methods.
When a transactional method is called by another transactional method, it must be specified how the transaction should propagate. For example: A method may continue to run in an existing transaction, or it may start a new transaction and run in its own transaction.

Possible values ​​for correct transaction propagation behavior are as follows:

  • 1.TransactionDefinition.PROPAGATION_REQUIRED: The most commonly used transaction propagation behavior, the @Transactional annotation we usually use is the default use of this transaction propagation behavior. If there is a current transaction, join the transaction; if there is no current transaction, create a new transaction.即:REQUIRED模式下,后来执行的事务融入之前的事务
  • 2.TransactionDefinition.PROPAGATION_REQUIRES_NEW: Create a new transaction, if there is a current transaction, suspend the current transaction. That is to say, regardless of whether the external method opens the transaction, the internal method modified by Propagation.REQUIRES_NEW will newly open its own transaction, and the opened transactions are independent of each other and do not interfere with each other.即:REQUIRED_NEW模式下,利用线程同步机制,先阻塞之前事务的线程,另起一个线程执行新的事务,事务提交后,再通知唤醒之前的事务,这种方式避免了后边事务的回归导致的先前事务的回滚
  • 3.TransactionDefinition.PROPAGATION_NESTED: If there is a transaction currently, create a transaction to run as a nested transaction of the current transaction; if there is no transaction currently, this value is equivalent to TransactionDefinition.PROPAGATION_REQUIRED.底层数据库在实现时,采用了save point a,保存点,当新事务执行完毕,再恢复保存点处 back to a
  • 4.TransactionDefinition.PROPAGATION_MANDATORY If there is a transaction currently, join the transaction; if there is no transaction currently, an exception is thrown, that is, the transaction environment is mandatory. (mandatory: Mandatory) This is rarely used.

If the following three transaction propagation behaviors are wrongly configured, the transaction will not be rolled back:

  1. TransactionDefinition.PROPAGATION_SUPPORTS: If there is a transaction currently, join the transaction; if there is no transaction, continue to run in a non-transactional manner.支持事务,有事务就加入支持,没有事务就按非事务方式执行,适合查询 / 只读业务
  2. TransactionDefinition.PROPAGATION_NOT_SUPPORTED: Run in non-transactional mode, if there is a current transaction, suspend the current transaction.即不支持事务,如果当前存在事务,挂起阻塞
  3. TransactionDefinition.PROPAGATION_NEVER: Runs in a non-transactional manner, throwing an exception if a transaction currently exists.

5-3 What are the isolation levels in Spring transactions?

Five constants representing isolation levels are defined in the TransactionDefinition interface:
其实就是在数据库事务隔离级别的基础上,加了默认隔离级别与数据库事务隔离级别保持一致。

  • 1. TransactionDefinition.ISOLATION_DEFAULT: Use the default isolation level of the back-end database, the REPEATABLE_READ isolation level adopted by Mysql by default, and the READ_COMMITTED isolation level adopted by Oracle by default.
  • 2. TransactionDefinition.ISOLATION_READ_UNCOMMITTED: The lowest isolation level, which allows reading uncommitted data changes, which may cause dirty reads, phantom reads, or non-repeatable reads
  • 3. TransactionDefinition.ISOLATION_READ_COMMITTED: Allows to read data that has been committed by concurrent transactions, which can prevent dirty reads, but phantom reads or non-repeatable reads may still occur
  • 4. TransactionDefinition.ISOLATION_REPEATABLE_READ: The results of multiple reads of the same field are consistent, unless the data is modified by the transaction itself, which can prevent dirty reads and non-repeatable reads, but phantom reads may still occur.
  • 5. TransactionDefinition.ISOLATION_SERIALIZABLE: The highest isolation level, which fully obeys the ACID isolation level. All transactions are executed one by one, so that there is no possibility of interference between transactions, that is, this level can prevent dirty reads, non-repeatable reads, and phantom reads. But this will seriously affect the performance of the program. Normally this level is not used either.

5-4 What are the disadvantages of declarative transactions?

  1. The declarative @Transactional acts on the method. In other words, if you need to add transactions to any part of the code, you need to separate this part of the code as a method. Other developers tend to overlook that the methods used are nested by transactions. If the following methods are added to the transaction method:
    • RPC call
    • file write
    • cache update
    • Message publishing
      These operations cannot be returned by themselves, which will lead to data inconsistency
  2. When there are multiple containers, a transaction manager needs to be specified. Therefore, when Spring is initialized, it is likely to load the wrong transaction manager and cause the transaction to fail. Therefore, when using the transaction manager in the system, you must specify the transaction manager alias, such as@Transactional(value = "emsTransactionManager")
  3. Even if the @Transactional tag is attached correctly, there are still many scenarios where transactions fail, and the scenarios are as follows:
    • The @Transactional tag is applied to non-public modified methods
    • The bean is not managed by the Spring container
    • The transaction method throws a non-runtime exception (Spring only rolls back the transaction for the RuntimeException exception by default. If the method throws a checked exception, the method will not perform subsequent operations, but will still submit the executed data operations. This may make Only part of the data is submitted, causing data inconsistency)
  4. Abusing aspects leads to failure: Spring transactions are implemented based on AOP. In actual projects, we will also use a lot of AOP to deal with different things, which are very likely to affect each other.
    If a classmate handles the exception in a certain aspect, it is likely to cause many transactions to fail

5-5 Transaction failure scenario?

  1. The database engine does not support transactions , such as the MyISAM engine does not support transactions.
  2. Bean is not managed by Spring
  3. The method is decorated with non-public or final , because the bottom layer of spring transactions uses AOP, and the jdk proxy obtains the cglib proxy, which will help us generate proxy classes and implement transaction functions in the proxy classes. If a method is modified by final, then in the proxy class, the method cannot be recreated and the transaction function can be added.
  4. Method internal call : the transaction method updateStatus() is directly called in the add() method; from the previous introduction, it can be seen directly that the updateStatus() method has the transaction capability because Spring AOP generates a proxy object, but this method directly calls this Object method, so the updateStatus() method will not generate a transaction. It can be seen that direct calls to methods in the same class will cause the transaction to fail.
@Service
public class UserService {
    
    
 @Autowired
 private UserMapper usermapper;

 public void add(User user){
    
    
  userMappper.insertUser(user);
  updateStatus(user);
 }
}

@Transactional
public void updateStatus(User user){
    
    
 doSomeThing();
}
  1. Multi-threaded call: two methods are not in one thread. The obtained database connection is also inconsistent, thus two different transactions.

SpringBoot

6-1 The principle of automatic configuration when Spring starts

1. The Spring boot class will be annotated with @SpringBootApplication, which can be regarded as a collection of three main annotations @Configuration, @ComponentScan and @EnableAutoConfiguration.
2. @Configuration declares that the startup class is the main configuration class, and @ComponentScan will scan the main configuration class and all classes under its package, and mark the class identified by the @Component annotation or the composite annotation of @Component, such as @Service, @Controller, @Repository, etc. are added to the Spring container.
3. The key point is the @EnableAutoConfiguration annotation, which can be regarded as a collection of @AutoConfigurationPackage and @Import annotations. The function of @AutoConfigurationPackage is to tell Spring Boot the scanning scope of the automatic configuration class. By default, it will be limited to the package where the main class is located and its subpackages. Search for auto-configuration classes. The AutoConfigurationImportSelector imported in the @Import annotation will call SpringFactoryLoader to add all the beans declared in the spring.factory file in the META-INF directory to the Spring container.

6-2 What is the working principle of SpringBoot Starter (starter)?

When Spring Boot starts:

  • When Spring Boot starts, it will look for the resources/META-INF/spring.factories file in the dependent Starter package,
    and then scan the Jar package that the project depends on according to the Jar package configured in the file.
  • Load the AutoConfigure class according to the spring.factories configuration
  • According to the conditions of the @Conditional annotation, perform automatic configuration and inject the Bean into the Spring container

When Spring Boot starts, it reads the configuration information of Spring Boot Starter according to the agreement, then initializes the resources according to the configuration information, and injects them into the Spring container. In this way, after Spring Boot is started, all resources have been prepared, and the corresponding Bean resources can be directly injected during use.

My shoe

Guess you like

Origin blog.csdn.net/baiduwaimai/article/details/132007749