Environment to prepare

1. The Bean definition

@Component
public class LagouBean {
    public void tech(a){
        System.out.println("java learning......"); }}Copy the code

Definition 2. The Aspect

@Component
@Aspect
public class LagouAspect {

    @Pointcut("execution(* com.lagou.*.*(..) )"
    public void pointcut(a){}@Before("pointcut()")
    public void before(a) {
        System.out.println("before method ......"); }}Copy the code

3. Test categories are as follows:

/** * Test case: Aop proxy object creation */
@Test
public void testAopProxyBuild(a){

    ApplicationContext applicationContext = newAnnotationConfigApplicationContext(SpringConfig.class);
    LagouBean lagouBean = applicationContext.getBean(LagouBean.class);
    lagouBean.tech();
}
Copy the code

We find that the LagouBean object was generated before the getBean (that is, done in the first line of initialization code) and that the object is a proxy object (Cglib proxy object). We conclude that the target Ban has completed the proxy and returned the proxy object during container initialization.

Proxy object creation process

Entry: After the bean is instantiated and its properties are populated and ready for initialization.

/** * This method does the IOC container creation and initialization work * the most important steps in this method are the second and eleventh steps ** /
@Override
public void refresh(a) throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      // STEP 1: refresh preprocessing
      // Preparations include setting the startup time, whether to activate the identity bit, and initializing the property source configuration
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      / / use DefaultListableBeanFactory is DefaultListableBeanFactory subclass
      // Initialize the bean factory

      / / STEP 2:
      / / a) to create the IoC container (DefaultListableBeanFactory)
      // b) load the parsed XML file (eventually stored in the Document object)
      // c) read the Document object and complete the loading and registration of BeanDefinition
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      // The most important method, prepare the bean factory
      // STEP 3: Preprocess the IoC container (set some common attributes)
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         // This method does not have any code in the current version of Spring, perhaps spring expects it to be extended in a later version
         // Empty shell method
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         // More important method
         // Execute the registered Factory Processors in spring's environment
         / / set custom ProcessorFactory and defined within a spring (ConfigutationClassPoetProcessor)
         / / spring BeanFactoryPostProcessor ConfigurationClassPostProcessor is maintained within a spring
         / / the following method in the main executive ConfigurationClassPostProcessor method
         // STEP 5: Call BeanFactoryPostProcessor to process BeanDefinition

         /** * BeanFactoryPostProcessor is one of spring's extension points. Spring allows BeanFactoryPostProcessor to read its configured metadata before the container instantiates any other beans * and can modify it as needed, For example, you can change the scope of the bean from Singleton to Prototype. You can also change the value of the property to * You can configure multiple spring BeanFactoryPostProcessor at the same time, and by setting the 'order' properties to control each spring BeanFactoryPostProcessor * BeanFactoryPostProcessor is executed after the Bean definition file is loaded by the Spring container and before the bean is instantiated
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         // The previous line of code already put some of the post-processors into bdMap, including the custom BeanPostProcessor
         // Register the BeanPostProcessor
         // Remove all the post-processors in bdMap,
         // Add some other post-processors to the factory list
         // STEP 6: Register the BeanPostProcessor
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         // Not important, internationalization processing
         // STEP 7: Initialize some message sources (such as i18N for internationalization)
         initMessageSource();

         // Initialize event multicaster for this context.
         // It is not important to handle the event
         // STEP 8: Initializes the application event broadcaster
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         // This is an empty shell method with no code in it
         // STEP 9: Initialize some special beans
         onRefresh();

         // Check for listener beans and register them.
         // Wait for some listener registrations
         STEP 10: Register some listeners
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         // key, key
         // Complete the bean instantiation
         // STEP 11: Instantiate the remaining singleton beans (not lazy-loaded)
         // Note: The IoC, DI, and AOP of beans all occur in this step
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         // STEP 12: Publish the corresponding events when the refresh is complete
         finishRefresh();
      }

      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }

         // Destroy already created singletons to avoid dangling resources.
         destroyBeans();

         // Reset 'active' flag.
         cancelRefresh(ex);

         // Propagate exception to caller.
         throw ex;
      }

      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...resetCommonCaches(); }}}Copy the code

Check the finishBeanFactoryInitialization (the beanFactory); That is as follows:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   
   // omit unimportant code
   
   // The most important code
   / / call the preInstantiateSingletons DefaultListableBeanFactory here
   // Instantiate all singleton objects
   beanFactory.preInstantiateSingletons();
}
Copy the code

Then: org. Springframework. Beans. Factory. Support. DefaultListableBeanFactory# preInstantiateSingletons

// Really call here, emphasis
@Override
public void preInstantiateSingletons(a) throws BeansException {
   if (logger.isDebugEnabled()) {
      logger.debug("Pre-instantiating singletons in " + this);
   }

   // Iterate over a copy to allow for init methods which in turn register new bean definitions.
   // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
   // Get all the classes to be initialized from bdMap
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

   // Trigger initialization of all non-lazy singleton beans...
   for (String beanName : beanNames) {
      // This line of code is not important, merge parent class BD, this application is rarely used
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      // Will definitely enter if
      // If the bean is not abstract, is singleton, and is not lazily loaded, do the following
      if(! bd.isAbstract() && bd.isSingleton() && ! bd.isLazyInit()) {// This is a FactoryBean
         if (isFactoryBean(beanName)) {
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            if (bean instanceof FactoryBean) {
               finalFactoryBean<? > factory = (FactoryBean<? >) bean;boolean isEagerInit;
               if(System.getSecurityManager() ! =null && factory instanceofSmartFactoryBean) { isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<? >) factory)::isEagerInit, getAccessControlContext()); }else {
                  isEagerInit = (factory instanceofSmartFactoryBean && ((SmartFactoryBean<? >) factory).isEagerInit()); }if(isEagerInit) { getBean(beanName); }}}else {
            / / the keygetBean(beanName); }}}}Copy the code

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
         // omit unimportant code
         
         // Focus on focus
         if (mbd.isSingleton()) {
            /** * getSingleton is equivalent to fetching the object from the cache based on the beanName, and if not, calling the createBean method of the anonymous inner class below */
            sharedInstance = getSingleton(beanName, () -> {
               try {
                  / / the key
                  / / call the AbstractAutowireCapableBeanFactory createBean method
                  return createBean(beanName, mbd, args);
               }
               catch (BeansException ex) {
                  // Explicitly remove instance from singleton cache: It might have been put there
                  // eagerly by the creation process, to allow for circular reference resolution.
                  // Also remove any beans that received a temporary reference to the bean.
                  destroySingleton(beanName);
                  throwex; }}); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }}return (T) bean;
}
Copy the code

Then check the org. Springframework. Beans. Factory. Support. AbstractAutowireCapableBeanFactory# createBean method

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
   // omit unimportant code

   try {
      // The method to actually instantiate the bean (and populate the property, initialize it) is in this line
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      
      returnbeanInstance; }}Copy the code
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   //BeanWrapper wraps a layer around the real object and getWrappedInstance in this class returns the real object
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      // Start creating wrapper classes for real objects, using reflection
      // The default call to construct the instantiated bean without arguments
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   // Here we take the native object from the wrapper class, not the proxy object, and then we change the native object into the proxy object
   finalObject bean = instanceWrapper.getWrappedInstance(); Class<? > beanType = instanceWrapper.getWrappedClass();if(beanType ! = NullBean.class) { mbd.resolvedTargetType = beanType; }// Allow post-processors to modify the merged bean definition.
   synchronized (mbd.postProcessingLock) {
      if(! mbd.postProcessed) {try {
            // Important
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         }
         catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Post-processing of merged bean definition failed", ex);
         }
         mbd.postProcessed = true; }}// Eagerly cache singletons to be able to resolve circular references
   // even when triggered by lifecycle interfaces like BeanFactoryAware.
   /** * Key steps to resolve loop dependencies */
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   // If you want to expose a single bean ahead of time, add the bean to the level 3 cache
   if (earlySingletonExposure) {
      if (logger.isDebugEnabled()) {
         logger.debug("Eagerly caching bean '" + beanName +
               "' to allow for resolving potential circular references");
      }
      // Important, be sure to check it out
      // Put the created object into the corresponding map
      SingleFactories (key besnName,value FactoryBean)
      //singletonFactory is obtained from the lamda expression
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
   }

   // Initialize the bean instance.
   Object exposedObject = bean;
   try {
      // Assign attribute, important
      // The attributes are populated by the Common and Autowired back-end processors
      Step 2: Populate the properties (DI dependency injection occurs in this step)
      populateBean(beanName, mbd, instanceWrapper);
      /** * this is where the native object is converted into a proxy object. < bESN init-method=""> the init-method method in this step is called */
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }
   return exposedObject;
}
Copy the code

Create the proxy object in the above code exposedObject = initializeBean(beanName, exposedObject, MBD); This line of code.

/** * this method is used to change a native object into a proxy object */
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
   if(System.getSecurityManager() ! =null) {
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
         invokeAwareMethods(beanName, bean);
         return null;
      }, getAccessControlContext());
   }
   else {
      invokeAwareMethods(beanName, bean);
   }

   Object wrappedBean = bean;
   if (mbd == null| |! mbd.isSynthetic()) {/ / the key
      /** * Preprocessor * executes BeanPostProcessor's Beforexxx method, is still a native object after the before method * has not completed the proxy, executes Afterxxx method, Can finish agent performs BeanPostProcessor postProcessBeforeInitialization method * * is the part before initialization method performs call * /
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }

   try {

      InitializingBean afterPropertiesSet InitializingBean afterPropertiesSet InitializingBean afterPropertiesSet InitializingBean
      invokeInitMethods(beanName, wrappedBean, mbd);
   }
   catch (Throwable ex) {
      throw newBeanCreationException( (mbd ! =null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
   }
   if (mbd == null| |! mbd.isSynthetic()) {// Rear processor
      // This section is called after the initialization method is executed
      / / the key
      // AOP is done here
      // After executing the Afterxxx method of the afterprocessor to turn a native object into a proxy object
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }

   return wrappedBean;
}
Copy the code

Then the code in the above wrappedBean = applyBeanPostProcessorsAfterInitialization (wrappedBean, beanName); This line of code.

// This method is used to turn a native object into a proxy object
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {

   Object result = existingBean;
   / / here will be a lot of post processor, but is done by AnnotationAutoProxyCreator agent
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
      / / but not in AnnotationAutoProxyCreator this method
      / / in the specific call AbstractAutoProxyCreator postProcessAfterInitialization method
      Object current = processor.postProcessAfterInitialization(result, beanName);
      if (current == null) {
         return result;
      }
      result = current;
   }
   return result;
}
Copy the code

Create a proxy object post processor AbstractAutoProxyCreator# postProcessAfterInitialization, because AbstractAutoProxyCreator also implements the BeanPostProcessor interface.

/** * call this method to complete the AOP process */
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
   if(bean ! =null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (this.earlyProxyReferences.remove(cacheKey) ! = bean) {// call this method specifically
         returnwrapIfNecessary(bean, beanName, cacheKey); }}return bean;
}
Copy the code

Then look at the wrapIfNecessary method

/** * Actually calls this method to complete the proxy */
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
   if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
      return bean;
   }
   if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
      return bean;
   }
   if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
      this.advisedBeans.put(cacheKey, Boolean.FALSE);
      return bean;
   }

   // Create proxy if we have advice.
   // Interceptors act like sections, parsing out all sections
   /** * Then see if your bean matches the pointcut expression of the aspect, execution..... , if it does, it will be ok. Otherwise, it will not be proxy
   Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
   if(specificInterceptors ! = DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);
      The createProxy method in the most important line of code completes the proxy
      Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
      this.proxyTypes.put(cacheKey, proxy.getClass());
      return proxy;
   }

   this.advisedBeans.put(cacheKey, Boolean.FALSE);
   return bean;
}
Copy the code

Then the createProxy method

protected Object createProxy(Class<? > beanClass,@Nullable String beanName,
      @Nullable Object[] specificInterceptors, TargetSource targetSource) {

   if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
      AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
   }

   // Create a proxy factory object to generate the proxy object
   ProxyFactory proxyFactory = new ProxyFactory();
   proxyFactory.copyFrom(this);

   // If the CGLIB proxy is not used
   if(! proxyFactory.isProxyTargetClass()) {if (shouldProxyTargetClass(beanClass, beanName)) {
         proxyFactory.setProxyTargetClass(true);
      }
      else{ evaluateProxyInterfaces(beanClass, proxyFactory); }}// More important
   // Get a collection of all associated advisors
   Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
   proxyFactory.addAdvisors(advisors);
   proxyFactory.setTargetSource(targetSource);
   customizeProxyFactory(proxyFactory);

   proxyFactory.setFrozen(this.freezeProxy);
   if (advisorsPreFiltered()) {
      proxyFactory.setPreFiltered(true);
   }

   // This method completes the proxy
   // Add interceptor or section to proxyFactory
   return proxyFactory.getProxy(getProxyClassLoader());
}
Copy the code

Then: org. Springframework. Aop. Framework. ProxyFactory# getProxy method,

public Object getProxy(@Nullable ClassLoader classLoader) {
   //1. Create JDK/CGLIB AOP proxy
   //2. Invoke AopProxy to create a Proxy object
   return createAopProxy().getProxy(classLoader);
}
Copy the code

1. Check the org. Springframework. Aop. Framework. ProxyCreatorSupport# createAopProxy method

protected final synchronized AopProxy createAopProxy(a) {
   if (!this.active) {
      activate();
   }
   // Call createAopProxy in DefaultAopProxyFactory
   return getAopProxyFactory().createAopProxy(this);
}
Copy the code

Then org. Springframework. Aop. Framework. DefaultAopProxyFactory# createAopProxy method

/ / the key
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
   / / config. IsProxyTargetClass () is a judgment is JDK or additional, ProxyTargetClass = true is additional
   if(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<? > targetClass = config.getTargetClass();if (targetClass == null) {
         throw new AopConfigException("TargetSource cannot determine target class: " +
               "Either an interface or a target is required for proxy creation.");
      }
      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
         // If the class is an interface, use the JDK dynamic proxy
         return new JdkDynamicAopProxy(config);
      }
      // This class does not implement cglib dynamic proxy
      return new ObjenesisCglibAopProxy(config);
   }
   else {
      // Here is the JDK dynamic proxy
      // The point is to actually call the getProxy method in JdkDynamicAopProxy
      return newJdkDynamicAopProxy(config); }}Copy the code

Return new ObjenesisCglibAopProxy(config); This line creates the AopProxy object.

2. Return to the above getProxy method, due to the additional dynamic proxy walk, so perform org. Springframework. Aop) framework. CglibAopProxy# getProxy method, as follows;

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
   if (logger.isDebugEnabled()) {
      logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
   }

   try{ Class<? > rootClass =this.advised.getTargetClass(); Assert.state(rootClass ! =null."Target class must be available for creating a CGLIB proxy"); Class<? > proxySuperClass = rootClass;if(ClassUtils.isCglibProxyClass(rootClass)) { proxySuperClass = rootClass.getSuperclass(); Class<? >[] additionalInterfaces = rootClass.getInterfaces();for(Class<? > additionalInterface : additionalInterfaces) {this.advised.addInterface(additionalInterface); }}// Validate the class, writing log messages as necessary.
      validateClassIfNecessary(proxySuperClass, classLoader);

      // Configure CGLIB Enhancer...
      Enhancer enhancer = createEnhancer();
      if(classLoader ! =null) {
         enhancer.setClassLoader(classLoader);
         if (classLoader instanceof SmartClassLoader &&
               ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
            enhancer.setUseCache(false);
         }
      }
      enhancer.setSuperclass(proxySuperClass);
      enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
      enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
      enhancer.setStrategy(newClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); Callback[] callbacks = getCallbacks(rootClass); Class<? >[] types =newClass<? >[callbacks.length];for (int x = 0; x < types.length; x++) {
         types[x] = callbacks[x].getClass();
      }
      // fixedInterceptorMap only populated at this point, after getCallbacks call above
      enhancer.setCallbackFilter(new ProxyCallbackFilter(
            this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
      enhancer.setCallbackTypes(types);

      // Generate the proxy class and create a proxy instance.
      return createProxyClassAndInstance(enhancer, callbacks);
   }
   catch (CodeGenerationException | IllegalArgumentException ex) {
      throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
            ": Common causes of this problem include using a final class or a non-visible class",
            ex);
   }
   catch (Throwable ex) {
      // TargetSource.getTarget() failed
      throw new AopConfigException("Unexpected AOP exception", ex); }}Copy the code

Looking at the Enhancer class, you can see that the underlying Cglib dynamic proxy is used to create proxy objects.