bean and loading JVM class loading Spring Spring assembly method of the Bean

background:

In using Google's open-source local database query caching solution often results in inefficient queries, database queries from good data into the cache, and then design the expiration time, and then get to design a method to obtain aggregated data cache to further process the entire package into a CacheSerice, and then call the Service Controller layer in, obtaining data from the Service.

problem:

CacheService need to be initialized, originally designed: When the Service bean that is loaded, which cache data has been initialized (namely the use of a database query Service to obtain data, and stuffed cache), and the initialization process is I put CacheService to the class constructor. The results have been published in the newspaper when a null pointer.

@Service("test")
public class Test implements IAppnameCache {

    @Autowired
    IAppnameService iAppnameService;
    public Test(){
        iAppnameService.queryAppname();// 抛出空指针
    }

    @Override
    public List<AppnameViewModel> get(String app){
        return iAppnameService.queryAppname();
    }
}

 

identify the problem:

After the query log and found a null pointer CacheService problem occurs when the constructor execution. Then there may be problems introduced Google open source library there may not be a process of elimination soon discovered the problem is not the problem the library, without Google open source library of test class employ such an approach has also undergone a null pointer.

Thinking question:

Since there is no relationship with the introduction of Google open source library, it shows that when (using the constructor) CacheService structured, which rely on other bean has not yet been constructed, resulting in a null pointer issues. Further study of the Spring bean configuration process for this problem.

Spring's bean loading process:

Main bean generation process is as follows:

1,AbstractBeanFactory.getBean(String)
2,AbstractBeanFactory.doGetBean(String, Class<T>, Object[], boolean)
3,DefaultSingletonBeanRegistry.getSingleton(String)
4,AbstractAutowireCapableBeanFactory.createBean(String, RootBeanDefinition, Object[])
5,AbstractAutowireCapableBeanFactory.doCreateBean(String, RootBeanDefinition, Object[])
6,AbstractAutowireCapableBeanFactory.createBeanInstance(String, RootBeanDefinition, Object[])
7,AbstractAutowireCapableBeanFactory.instantiateBean(String, RootBeanDefinition)
8,SimpleInstantiationStrategy.instantiate(RootBeanDefinition, String, BeanFactory)
9, AbstractAutowireCapableBeanFactory.populateBean(String, RootBeanDefinition, BeanWrapper)
10,AbstractAutowireCapableBeanFactory.initializeBean(String, Object, RootBeanDefinition)
11,AbstractAutowireCapableBeanFactory.invokeAwareMethods(String, Object)
12,AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(Object, String)
13,AbstractAutowireCapableBeanFactory.invokeInitMethods(String, Object, RootBeanDefinition)
14,AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(Object, String)

  

(1) In the instance of an object by acquiring bean BeanFactory time, will go to find a single embodiment example corresponding to whether the collection has been created, if there is a direct return, this is the first acquisition, there is no get;

(2) then obtains corresponding AbastractBeanFactory BeanDefinition objects bean by name, BeanDefinition objects represent various classes corresponding metadata, so the object can be determined according to whether BeanDefinition single embodiment, dependent on whether other objects, other objects if dependent so Mr. into its reliance, here is the recursive call.

Before step 7 is to prepare to generate bean, bean is actually generated in AbstractAutowireCapableBeanFactory of instantiateBean method:

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
	try {
		Object beanInstance;
		final BeanFactory parent = this;
		if (System.getSecurityManager() != null) {
			beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
				@Override
				public Object run() {
					return getInstantiationStrategy().instantiate(mbd, beanName, parent);
				}
			}, getAccessControlContext());
		}
		else {
			beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
		}
		BeanWrapper bw = new BeanWrapperImpl(beanInstance);
		initBeanWrapper(bw);
		return bw;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
	}
}

-----------------------------------------------------------------------------------------------------
	@Override
	public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) { // Don't override the class with CGLIB if no overrides. if (bd.getMethodOverrides().isEmpty()) { Constructor<?> constructorToUse; synchronized (bd.constructorArgumentLock) { //这里一堆安全检查 } //默认使用构造函数利用反射实例化bean return BeanUtils.instantiateClass(constructorToUse); } else { // Must generate CGLIB subclass. return instantiateWithMethodInjection(bd, beanName, owner); } }

  In fact you can see the bean is generated directlyBeanUtils工具类通过反射获取类的实例。

Get reflected class instance is as follows:

<?> Class cls = Class.forName ( "cn.mldn.demo.Person"); // Class object acquired 
Object obj = cls.newInstance () // instantiate the object reflector 
<?> Constructor cons = cls.getConstructor ( String.class, int.class); // get the constructor 
method m3 = cls.getDeclaredMethod ( "getName" ); // get get method 
Field nameField = cls.getDeclaredField ( "name" ); // get the name attribute

At the same time when the class is loaded in the JVM, then to initialize this step, the first thing would be to call the default constructor to initialize variables:

  • Class constructor <clinit> () method is the assignment operation compiler automatically collected class all class variables and static statement block merger of (static block) in the statement, the order compiler collected by the statement in the source file appear in the order determined by a static statement block only access to the static variables defined in a block of statements before and after it is defined in the variable, you can assign fast in front of the static statements, but can not be accessed.
  • Class constructor <clinit> () method of the class constructor (instance constructor <init> () method) different, it does not explicitly call parent class configuration, the virtual machine is performed to ensure that the subclass <clinit> () method before the parent class <clinit> () method has been completed. Thus the class in the virtual machine the first <clinit> perform () method must be java.lang.Object.
  • As the parent of <clinit> () method performs first, which means static statements as defined in the parent class is about to take precedence over variable subclass assignment.
  • <Clinit> () method for the class or interface is not necessary, if a class does not static statements, nor manipulated variable assignment, the compiler may not be generated for the class <clinit> () method. (The default is given when the memory allocation, regardless of the initialization process)
  • Interface block static statements can not be used, but with different interfaces and classes that implements the interface <clinit> () method does not need to run a parent interface <clinit> () method. Only when the parent variables defined in the interface is used, the parent interface will be initialized. Further, the interface implementation class in the initialization was not executed <clinit> () interface method.
  • Virtual opportunity to ensure that a class <clinit> () method is correctly locked in a multithreaded environment, and synchronization, if multiple threads to initialize a class, then there will only be one thread execution of this class <clinit> () method other threads are blocked need to wait until the active thread execution <clinit> () method is completed. If a class <clinit> () method takes a long time there is an operation, it may result in multiple processes obstruction.

CacheService behavior is not a class assignment, then the default constructor will be called, so CacheService class, the constructor is acquired reflection time will explicitly call constructors. Return to this issue in the constructor of the other bean, and the bean Spring generate is actually no law (that is, dependent bean has not been injected), so the null pointer exception is thrown.

So the question is, Spring said yes with automatic detection relies functions?


Dear readers, please look down slowly, please niche for you to unpack.

We look forward to look, if you did not get the target bean in the container, then AbastractBeanFactory will get corresponding BeanDefinition target bean by name, BeanDefinition object represents various metadata corresponding to the class,

// Run bean described here has not been created, to obtain bean dependent bean 
String [] The dependsOn mbd.getDependsOn = (); 
IF (= null The dependsOn!) { 
  For (DEP String: The dependsOn) { 
	IF (isDependent (the beanName , DEP)) { 
	  the throw new new BeanCreationException (mbd.getResourceDescription (), the beanName, 
		"The depends Circular-Relationship BETWEEN ON '" + the beanName + "' and '" + DEP + "'"); 
		} 
	registerDependentBean (DEP, the beanName); 
	// instantiate dependent the bean 
	the getBean (DEP); 
  } 
}

It can be seen by the acquired dependent getDependsOn method bean, and this process is injected through the CacheService Setter properties bean, and then obtain bean. Well, since the properties of the injection time

IAppnameService has been completed into a bean, or why the constructor throws an exception it? The original injection clear that this process is dependent, that is added depends-on (also supports annotations) in the bean configuration,
if not configured, then CacheService property is injected after getbean () to complete. So in the implementation of the constructor throws an exception, of course, CacheService it! So that Spring's dependency checking did not actually open,
is the need to manually open the configuration file, there are four dependency checking manner in Spring. Dependency checking has four modes: simple, objects, all, none , are set by the mode attribute dependency-check bean.

Of course, the loading process in Spring, which is loading or follow the loading process of the JVM.


The main loading process of the JVM

(To be continued) References:
1. JVM-depth understanding of virtual machine
2. https://blog.51cto.com/wenshengzhu/1950146
3. https://blog.csdn.net/h12kjgj/article/details/54312766
4
. https://www.cnblogs.com/kjitboy/p/12076303.html [ the Spring assembly manner Bean

Guess you like

Origin www.cnblogs.com/jihuabai/p/12129357.html