Spring source code learning < I > spring underlying core principles

1. How to create an object in spring
 

@Component
public class UserService  {
	public void test(){
		System.out.println("test");
	}

@ComponentScan("com.shen")

public class AppConfig {
}

public class Test {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

		UserService userService = (UserService) context.getBean("userService");
	    userService.test();
	}
}

Those who have used Spring should be particularly familiar with the above lines of code, which is the creation of spring Bean when we call context When getBean ("UserService"), an object will be created. So how does its bottom layer know that "UserService" corresponds to the UserService class?
We can analyze that some things will be done when calling the construction method of AnnotationConfigApplicationContext:
① Resolve AppConfig Class to get the scan path
② Traverse all Java classes under the scanning path. If @ Component, @ service and other annotations are found on a class, spring will record the class, which may be stored in a collection similar to map < string, class >.
③ Spring will generate the beanName corresponding to the current class according to a rule, store it in the Map as a key, and the current class as a value.

So, when we call context When getBean ("userservice"), you can find the userservice class according to "userservice", so you can create the object

2.Bean creation process
How does Spring create a Bean?
In fact, the life cycle of Bean creation can be roughly divided into the following steps:
userService. Class - > constructor - > normal object - > dependency injection (attribute assignment) - > pre initialization (@ postconstruct) - > initialization (initializingbean) - > post initialization (AOP) - > proxy object - > bean

Construction method: first of all, we consider that it is generated through the default parameterless construction. If there is no parameterless construction or there are multiple construction methods, how will spring choose?
 

public class Test {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

		UserService userService = (UserService) context.getBean("userService");
		userService.test();


	}
}

@Component
public class OrderService {
}

@Component
public class UserService  {
	private OrderService orderService;
	public void test(){
		System.out.println("test");
	}

	public UserService() {
		System.out.println("1");
	}

	public UserService(OrderService orderService) {
		this.orderService = orderService;
		System.out.println("2");
	}

	public UserService(OrderService orderService,OrderService orderService1) {
		this.orderService = orderService;
		this.orderService = orderService1;
		System.out.println("3");
	}
}

public class Test {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

		UserService userService = (UserService) context.getBean("userService");
		userService.test();


	}
}

@Component
public class OrderService {
}

@Component
public class UserService  {
	private OrderService orderService;
	public void test(){
		System.out.println("test");
	}

//	public UserService() {
//		System.out.println("1");
//	}

	public UserService(OrderService orderService) {
		this.orderService = orderService;
		System.out.println("2");
	}

//	public UserService(OrderService orderService,OrderService orderService1) {
//		this.orderService = orderService;
//		this.orderService = orderService1;
//		System.out.println("3");
//	}
}

public class Test {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

		UserService userService = (UserService) context.getBean("userService");
		userService.test();


	}
}

@Component
public class OrderService {
}

@Component
public class UserService  {
	private OrderService orderService;
	public void test(){
		System.out.println("test");
	}

//	public UserService() {
//		System.out.println("1");
//	}

	public UserService(OrderService orderService) {
		this.orderService = orderService;
		System.out.println("2");
	}

	public UserService(OrderService orderService,OrderService orderService1) {
		this.orderService = orderService;
		this.orderService = orderService1;
		System.out.println("3");
	}
}

As can be seen from the above three test cases, the spring bottom layer uses the parameterless structure to create bean s by default. If there is no parameterless structure, it will look for the parameterless structure. If there are multiple parameterless structures, it will throw an exception.
If we don't have a parameterless construct, but there are multiple parametered constructs, how can we tell spring which parametered construct to use? In fact, we only need to add an @ autowritten annotation to solve it
 

public class Test {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

		UserService userService = (UserService) context.getBean("userService");
		userService.test();


	}
}

@Component
public class OrderService {
}

@Component
public class UserService  {
	private OrderService orderService;
	public void test(){
		System.out.println("test");
	}

//	public UserService() {
//		System.out.println("1");
//	}
	@Autowired
	public UserService(OrderService orderService) {
		this.orderService = orderService;
		System.out.println("2");
	}

	public UserService(OrderService orderService,OrderService orderService1) {
		this.orderService = orderService;
		this.orderService = orderService1;
		System.out.println("3");
	}
}

3. Initialization process

There is an initialization process in the process of spring creating beans, which is divided into before initialization, during initialization and after initialization. Before initialization, that is, after generating objects and injecting dependencies, you can use the @ PostConstruct annotation to indicate
 

@Component
public class UserService  {
	@PostConstruct
	public void test1(){
		System.out.println("Before initialization....");
	}
	public void test(){
		System.out.println("test");
	}

}

public class Test {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

		UserService userService = (UserService) context.getBean("userService");
//		userService.test();
	}
}


During initialization, that is, when a class implements InitializingBean, it overrides the afterpropertieset method

@Component
public class UserService  implements InitializingBean {
	@PostConstruct
	public void test1(){
		System.out.println("Before initialization....");
	}
	public void test(){
		System.out.println("test");
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("During initialization....");
	}
}

public class Test {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

		UserService userService = (UserService) context.getBean("userService");
		userService.test();
	}
}

After initialization is what we call the AOP process

//Define a slice
@Aspect
@Component
public class ShenAspect {


	@Before("execution(public void com.shen.service.UserService.test())")
	public void zhouyuBefore(JoinPoint joinPoint) {
		System.out.println("After initialization...");
	}

}
@Component
@EnableAspectJAutoProxy
public class UserService  implements InitializingBean {
	@PostConstruct
	public void test1(){
		System.out.println("Before initialization....");
	}
	public void test(){
		System.out.println("test");
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("During initialization....");
	}
}
public class Test {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

		UserService userService = (UserService) context.getBean("userService");
		userService.test();
	}
}

 4.AOP general process
AOP is to perform dynamic proxy. In the process of creating a bean, spring will judge whether the bean currently being created needs AOP in the last step, and perform dynamic proxy if necessary
How to determine whether the current Bean object needs AOP:
① Find the slice Bean of the index
② Traverse the methods in the section to see if @ Before, @ After and other annotations are written
③ If it is written, judge whether the corresponding Pointcut matches the class of the current Bean object
④ If it matches, it indicates that the current Bean object has a matching Pointcut, indicating that AOP is required

General process of AOP with Cglib:
① The production proxy class UserServiceProxy inherits UserService
② The proxy class overrides the methods of the parent class, such as the test() method in UserService
③ The proxy class also has a target attribute whose value is the proxied object
④ Logic when test () method in proxy class is executed: execute facet logic (@ Before) and call target test() method
5 Spring transactions
When we add @ Transactional annotation to a method, it means that the Spring transaction will be opened when the method is called, and the Bean object corresponding to the class of this method will be the proxy object of this class.
Steps for executing a method by proxy object of Spring transaction:
① Judge whether the currently executed method has @ Transactional annotation
② If so, create a new database connection using the transaction manager
③ Modify the autocommit of the database connection to false
④ Execute target Test (), execute the business logic code written by the programmer, that is, execute sql
⑤ If there is no exception after execution, commit, otherwise rollback

Keywords: Java Spring

Added by easethan on Thu, 16 Dec 2021 10:28:40 +0200