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.