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:
- Before: The pre-notification corresponds to @before
- After: The post-notification corresponds to @after
- Return: Returns a notification corresponding to @afterRETURNING
- Around: The surround notification corresponds to @
- 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,FactoryBean
andObjectFactory
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:
BeanFactory
Only one is provided by itselfBean
Object acquisition,ApplicationContext
According toBean
The name gets more than oneBean
theList
Secondly, also inheritedHierarchicalBeanFactory
, implement hierarchy or parent-child structure, etc. - Increase internationalization (
MessageSource
) : Added internationalization support - Multipathing Configuration (
ResourceLoader
Support) :ClassPath Xml
andFileSystem XML
And other configuration modes. - Event Publishing mechanism (
ApplicationEventPublisher
) : Added event listening and event publishing.
9 Common Design patterns in Spring
- Simple Factory model:
BeanFactory
This simple factory pattern, also known as the static factory pattern, is used to create objects - Factory Method:
FactoryBean
That’s the way it works - Proxy pattern: This is the most common; AOP, interceptors, and so on are used
JDK 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 with
Wrapper
, such asBeanWrapper
Both use decorator patterns to enhance the properties of objects. - Adapter mode: in
Spring MVC
Inside, more importantHandlerAdapter
The adaptor pattern is used to fit different typesHandler
- Template method:
RedisTemplate, jdbcTemplate
Is 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
- Instantiation: Bean init, implement reflection create object
- Initialization: populateBean implements the population of object attributes, using a level 3 cache
- Aware interface implementation: BeanAware interface check, such as BeanNameAware, BeanFactoryNameAware, etc., can be set properties
- BeanPostProcesser preprocessing: @PostConstruct is triggered when the preprocessor executes
- Execute the afterPropertiesSet method of InitializingBean
- Execute the init-method method
- Execute the BeanPostProcessor post method
- See if the relevant DisposableBean interface is implemented
- Execute the deStory method
Common extension points for Spring beans
- The use of various Aware interfaces, such as BeanNameAware, can be overwritten to BeanName
- 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
- AOP proxies and @postConstruct initialization can be done in BeanPostProcessor
- 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
- 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.
- 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.
- 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_NEW
If 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:
- The underlying database engine does not support transactions and only InnoDB can use transactions
- Without injecting beans into the Spring container, beans cannot be container-managed and therefore cannot use proxies.
- Internal calls are invalid because AOP proxies use the this pointer instead of Spring proxies.
- An exception occurs, but the exception is caught and not thrown, in which case the external transaction cannot be rolled back.
- 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.
- 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:
- The user sends a request to the front-end controller
DispatcherServlet
DispatcherServlet
A request is received to invoke the processor mapperHandlerMapping
.- The processor mapper finds the specific processor based on the request URL and generates the processor execution chain
HandlerExecutionChain
Both the processor object and the processor interceptorDispatcherServlet
. DispatcherServlet
Per processorHandler
Get processor adapterHandlerAdapter
performHandlerAdapter
Handle a series of operations, such as: parameter encapsulation, data format conversion, data validation, etc- Execution processor
Handler
(Controller
, also known as page controller). Handler
Return after executionModelAndView
HandlerAdapter
willHandler
The execution resultModelAndView
Return to theDispatcherServlet
DispatcherServlet
willModelAndView
To pass toViewReslover
View parserViewReslover
Returns concrete after parsingView
DispatcherServlet
rightView
Render the view (that is, model datamodel
Fill to view).DispatcherServlet
Respond 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 exceptionsViewResolver
: 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 returnedLocaleResolver
: Internationalization conversionThemeResolver
Theme:MultipartResolver
: File uploadFlashMapManager
(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.