SpringAOP implementation source code interpretation

1, Spring AOP examples

Based on a brief introduction how to implement Spring AOP programming (in the way the target object annotation method weaving notification method)

2, AOP key notes @EnableAspectJAutoProxy

Analysis @EnableAspectJAutoProxy source notes, understand the need to implement AOP configuration information provided by the container

3, AOP to achieve key classes AnnotationAwareAspectJAutoProxyCreator

Static analysis inside the Spring Framework to create AOP proxy object of the class

4, AnnotationAwareAspectJAutoProxyCreator instantiation and registration

Dynamic Analysis AnnotationAwareAspectJAutoProxyCreator instantiation and registration process in the container

5, AnnotationAwareAspectJAutoProxyCreator create the target proxy object

Dynamic analysis using AnnotationAwareAspectJAutoProxyCreator Spring container to create a proxy object target process

01

Spring AOP examples

This sample code project is based on Maven, and using Spring5.0.5 version, pom.xml as follows:

4.0.0

cn.com.tuling.openclass.aop

explore-06-spring-aop

0.0.1-SNAPSHOT

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

<java.version>1.8</java.version>

<spring.version>5.0.5.RELEASE</spring.version>

org.springframework

spring-context

${spring.version}

org.aspectj

aspectjweaver

1.8.13

junit

junit

4.7

test

(Sliding around to see the complete code)

The current sample is relatively simple, directly attached to the code is as follows:

1)IPowerService和PowerServiceImpl

Target class interface and implementation, a login method on the inside, the notification method for weaving the AOP

package cn.com.tuling.openclass.service;

public interface IPowerService {

public boolean login(String userName,String password);

}

package cn.com.tuling.openclass.service.impl;

import org.springframework.stereotype.Service;

import cn.com.tuling.openclass.service.IPowerService;

@Service

public class PowerServiceImpl implements IPowerService {

@Override

public boolean login(String userName, String password) {

boolean bool = false;

System.out.println(“to execute PowerServiceImpl.login() method…”);

bool = userName != null && userName.startsWith(“zhang”);

return bool;

}

}

2)LogServiceImpl

This log which defines several methods, in order to notify the package, woven into a pointcut

package cn.com.tuling.openclass.service.impl;

import org.aspectj.lang.annotation.After;

import org.aspectj.lang.annotation.AfterReturning;

import org.aspectj.lang.annotation.AfterThrowing;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.aspectj.lang.annotation.Pointcut;

import org.springframework.stereotype.Component;

@ Component // declare the current class for a component class

@ Aspect // section

public class LogServiceImpl{

// define the starting point

@Pointcut(“execution(* cn.com.tuling….(…))”)

public void myPointCut(){}

The method of packaging into logBefore // Before notification, woven into myPointCut () pointcut br /> Before @ ( "myPointCut ()")
public void logBefore () {
}
// methods packaged into the logAfter After notification, woven into myPointCut () entry point
@After ( "myPointCut ()")
br /> System.out.println ( "logServiceImpl.logBefore .... ...." );
}
// methods packaged into the logAfter After notification, woven into myPointCut () entry point
@After ( "myPointCut ()")
public void logAfter () {}
// The method of packaging into AfterReturning logReturnAfter notification, woven into myPointCut () entry point
@AfterReturning ( "myPointCut ()")
br /> System.out.println ( "logServiceImpl.logAfter .... ...." );
}
// will logReturnAfter method of packaging into AfterReturning notification, woven into myPointCut () entry point
@AfterReturning ( "myPointCut ()")
public void logReturnAfter () {}
// The method of packaging into AfterThrowing logThrowing notification, woven into myPointCut () entry point for
the @AfterThrowing ( "myPointCut ()")
br /> System.out.println ( "logServiceImpl.logReturnAfter .... ...." );
}
// will logThrowing method of packaging into AfterThrowing notification, woven into myPointCut () entry point for
the @AfterThrowing ( "myPointCut ()")
public void logThrowing () {
System.out.println ( ".... logServiceImpl.logThrowing .... ");
}
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
10
. 11
12 is
13 is
14
15
16
. 17
18 is
. 19
20 is
21 is
22 is
23 is
}

3)ConfigAOP

Spring annotation configuration class of formula

package cn.com.tuling.openclass.config;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.annotation.EnableAspectJAutoProxy;

@ Configuration // declare the current class for Spring annotation configuration class

@ EnableAspectJAutoProxy // AspectJ annotation support

@ComponentScan (basePackages = "cn.com.tuling.openclass") // automatically scan path assembly

public class ConfigAOP {

}

4) TestAOP, test class

package cn.com.tuling.openclass.service;

import org.junit.Test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import cn.com.tuling.openclass.config.ConfigAOP;

public class TestAOP {

@Test

public void test01(){

// Initialize the Notes formula IOC container

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigAOP.class);

// Get PowerService instance from vessel

IPowerService powerService = (IPowerService)ctx.getBean(IPowerService.class);

// call the login method PowerService

boolean bool = powerService.login(“zhangsan”, “123”);

// Close IOC container

ctx.close();

}

}

TestAOP running inside test01 method, run the following log:

We test01 method TestAOP in, just call the login method IPowerService, but its output before and after printing each notification, explanation has been based on the Spring AOP, the completion of the notification to the target entry point for weaving.

02

AOP key notes @EnableAspectJAutoProxy

By adjusting our previous code ConfigAOP class, we can feel, if commented ConfigAOP class above @EnableAspectJAutoProxy, run TestAOP method of test01 time, will not see the notice woven into effect (only in the execution PowerServiceImpl login method, does not perform LogServiceImpl corresponding notification method), indicating @EnableAspectJAutoProxy notes inside, defines the critical information woven into the notice of SpringAOP, what is it this information, we examine @EnableAspectJAutoProxy source.

package org.springframework.context.annotation;

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

/**

支持AspectJ注解,使用注解的方式实现AOP织入,效果等同xml配置文件中的aop:aspectj-autoproxy/
@author Chris Beams
@author Juergen Hoeller
@since 3.1
@see org.aspectj.lang.annotation.Aspectbr/>/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
br/>@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/
Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
to standard Java interface-based proxies. The default is {@code false}.
/
boolean proxyTargetClass() default false;
/

Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
. The Via Retrieval for {} class @link org.springframework.aop.framework.AopContext
Off by default, IE NO Guarantees that @code AopContext} {Access Will Work.
@Since 4.3.1
* /
Boolean the exposeProxy () to false default;
}
by looking @EnableAspectJAutoProxy source code, we understand the role of @EnableAspectJAutoProxy, with aop xml configuration file: Like aspectj-autoproxy, tell the Spring container to support annotation type Aspect.

@EnableAspectJAutoProxy has two attributes:

1) proxyTargetClass specify whether to use CGLIB way to create a proxy object interface of the goal. The default value is false, create an interface object using JDK proxy mode

exposeProxy whether the object should be labeled Agent aop frame by a AopContext ThreadLocal exposed to form. When a proxy object to call its own methods of another agency, this property will be very useful. Default Yes Yes false, in order to avoid unnecessary interception.
Use case exposeProxy property, see the other topics ( "pit, pit, pit, cut into the same ineffective methods in a class!"), not repeat it here.

Throughout the previous code, no place has described how to achieve AOP, but have found that the red lines of code, you have a relationship from the name with our goal of AOP (AspectJ section), we like to go and see AspectJAutoProxyRegistrar class source code is as follows:

package org.springframework.context.annotation;

import org.springframework.aop.config.AopConfigUtils;

import org.springframework.beans.factory.support.BeanDefinitionRegistry;

import org.springframework.core.annotation.AnnotationAttributes;

import org.springframework.core.type.AnnotationMetadata;

/**

… …
*/
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
br/>@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean(“proxyTargetClass”)) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean(“exposeProxy”)) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy (Registry);
}
}
}
}
In AspectJAutoProxyRegistrar.java source, the red mark portion can be guessed from the name, is a method call to complete the annotation creator proxy object (Creator) row, continued this line of thought, we follow up the red part of the code as follows:

public abstract class AopConfigUtils {

… …

@Nullable

public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {

return registerAspectJAutoProxyCreatorIfNecessary(registry, null);

}

@Nullable

public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,

@Nullable Object source) {

return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);

}

… …

}

AopConfigUtils with the source code, we will eventually find the calling code section marked in red, the role of the lines of code, is a registered AspectJAwareAdvisorAutoProxyCreator class in the container.

Here, we found a SpringAOP, create a source (as figurines) proxy object of the target object. This is to inform the person making the figurines Spring IOC container in @EnableAspectJAutoProxy, that is, by @EnableAspectJAutoProxy notes, notice Spring container when needed, create a proxy target object using AspectJAwareAdvisorAutoProxyCreator object implementing the weaving notification (to achieve AOP).

03

AnnotationAwareAspectJAutoProxyCreator class static source code analysis

effect:

Code level:

AnnotationAwareAspectJAutoProxyCreator

->AspectJAwareAdvisorAutoProxyCreator

->AbstractAdvisorAutoProxyCreator

->AbstractAutoProxyCreator

->ProxyProcessorSupport

implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware (automatic assembly Bean)

SmartInstantiationAwareBeanPostProcessor

->InstantiationAwareBeanPostProcessor

-> BeanPostProcessor (post processor)

Postprocessor: Spring important component in the IOC during the initialization container, add new features

Automatic assembly Bean (Aware): the target object is a target acquisition system interface

Function Code:

bstractAutoProxyCreator.setBeanFactory (BeanFactory) // Aware, get the Spring BeanFactory objects

AbstractAutoProxyCreator.postProcessBeforeInstantiation () // initialize pre-post processor add functionality
to determine whether there advisedBeans contains the current beanName, whether it is the foundation class notes, or if it contains a base class, or null
if not, create a proxy object of the target object
AbstractAdvisorAutoProxyCreator. setBeanFactory ()
super.setBeanFactory ()
initBeanFactory () // template methods
AnnotationAwareAspectJAutoProxyCreator.initBeanFactory ()
super.initBeanFactory ()
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
10
. 11
12 is
13 is
14
15
04

AnnotationAwareAspectJAutoProxyCreator instantiation and registration

Up to now, we grope according to the source code, class AspectJAwareAdvisorAutoProxyCreator basically found the key to achieve AOP, and that objects of this class when instantiated, and at what time AOP proxy object created it? Can answer that question, AOP principle we are not to get.

Next, we first study the creation AspectJAwareAdvisorAutoProxyCreator object.

We AnnotationConfigApplicationContext ctx TestAOP's method in the test01 = new AnnotationConfigApplicationContext (ConfigAOP.class); the code, add a debug, the manner in debug, follow the code, after the following:

AnnotationConfigApplicationContext.AnnotationConfigApplicationContext(Class … annotatedClasses)

->AbstractApplicationContext.refresh()

Code refresh method is as follows:

// Context initialization container (such as a container starting time, etc.)

prepareRefresh();

// Create beanFactory container object, that has re-create destroyed, not previously, creating a new object

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Initialize beanFactory. (Class loader, Application ... Processor, Aware, environmental objects, etc.)

prepareBeanFactory(beanFactory);

try {

// template method, after loading the Bean definitions, may be modified to provide an inlet for the subclass of BeanFactory

postProcessBeanFactory(beanFactory);

// Call register in the container processor BeanFactory

invokeBeanFactoryPostProcessors(beanFactory);

// Register Bean post-processors, these processors will be called when the object is created Bean

registerBeanPostProcessors(beanFactory);

// initialize resources

initMessageSource();

// Initialize the container event broadcaster

initApplicationEventMulticaster();

// template method, to provide an opportunity for a subclass to instantiate other special bean in a container

onRefresh();

// detect and register the listener

registerListeners();

// singleton object instantiates other non-delay-loaded.

finishBeanFactoryInitialization(beanFactory);

// release container events

finishRefresh();

}

… …

By looking at AspectJAwareAdvisorAutoProxyCreator parent class and implementation class, we can actually find AspectJAwareAdvisorAutoProxyCreator BeanPostProcessor a subclass, so in the Spring, the method is successful red statement (registerBeanPostProcessors) in the refresh process completed. We debug method to registerBeanPostProcessors go, the path is as follows:

AnnotationConfigApplicationContext(AbstractApplicationContext).refresh() line: 535

->AnnotationConfigApplicationContext(AbstractApplicationContext).registerBeanPostProcessors(ConfigurableListableBeanFactory) line: 710
->PostProcessorRegistrationDelegate.registerBeanPostProcessors(ConfigurableListableBeanFactory, AbstractApplicationContext) line: 189
1
2
3
PostProcessorRegistrationDelegate.registerBeanPostProcessors(ConfigurableListableBeanFactory,

The AbstractApplicationContext Code) method is as follows:

String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

// Register BeanPostProcessorChecker that logs an info message when

// a bean is created during BeanPostProcessor instantiation, i.e. when

// a bean is not eligible for getting processed by all BeanPostProcessors.

int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;

beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

// Separate between BeanPostProcessors that implement PriorityOrdered,

// Ordered, and the rest.

List priorityOrderedPostProcessors = new ArrayList<>();

List internalPostProcessors = new ArrayList<>();

List orderedPostProcessorNames = new ArrayList<>();

List nonOrderedPostProcessorNames = new ArrayList<>();

for (String ppName : postProcessorNames) {

if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {

BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);

priorityOrderedPostProcessors.add(pp);

if (pp instanceof MergedBeanDefinitionPostProcessor) {

internalPostProcessors.add(pp);

}

}

else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {

orderedPostProcessorNames.add(ppName);

}

else {

nonOrderedPostProcessorNames.add(ppName);

}

}

// First, register the BeanPostProcessors that implement PriorityOrdered.

sortPostProcessors(priorityOrderedPostProcessors, beanFactory);

registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

// Next, register the BeanPostProcessors that implement Ordered.

List orderedPostProcessors = new ArrayList<>();

for (String ppName : orderedPostProcessorNames) {

BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);①

orderedPostProcessors.add(pp);

if (pp instanceof MergedBeanDefinitionPostProcessor) {

internalPostProcessors.add(pp);

}

}

sortPostProcessors(orderedPostProcessors, beanFactory);

registerBeanPostProcessors(beanFactory, orderedPostProcessors);②

// Now, register all regular BeanPostProcessors.

List nonOrderedPostProcessors = new ArrayList<>();

for (String ppName : nonOrderedPostProcessorNames) {

BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);

nonOrderedPostProcessors.add(pp);

if (pp instanceof MergedBeanDefinitionPostProcessor) {

internalPostProcessors.add(pp);

}

}

registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

// Finally, re-register all internal BeanPostProcessors.

sortPostProcessors(internalPostProcessors, beanFactory);

registerBeanPostProcessors(beanFactory, internalPostProcessors);

// Re-register post-processor for detecting inner beans as ApplicationListeners,

// moving it to the end of the processor chain (for picking up proxies etc).

beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));

The above code, probably thinking is this:

1) get all beanName BeanPostProcessor container, that is, when we registered in the Spring container bean id or name

2) depending on whether BeanPostProcessor achieved PriorityOrdered, Ordered, BeanPostProcessor general classification of the Processor

3) Press PriorityOrdered, Ordered, the order of the general class, and initializes the corresponding register BeanPostProcessor

We can look AnnotationAwareAspectJAutoProxyCreator parent, you will find that it is realized (actually a subclass of ProiorityOrdered is Ordered) Ordered interface, so AnnotationAwareAspectJAutoProxyCreator the object is instantiated in a red mark above ① code, the code is registered in ② beanFactory middle. Which beanFactory.getBean (...) method, the object is Spring obtain a uniform way, detailed process, we carry out the code track in the back, where we remember being inside getBean method to complete the creation AnnotationAwareAspectJAutoProxyCreator object, and completed by AnnotationAwareAspectJAutoProxyCreator ② Code registration (created in the container object, and preserved, beanName is org.springframework.aop.config.internalAutoProxyCreator)

05

AnnotationAwareAspectJAutoProxyCreator create the target proxy object

Earlier we understand the process of creation and registration AnnotationAwareAspectJAutoProxyCreator Spring object, in this section, we will study how to create a Spring AOP proxy object using the registered good AnnotationAwareAspectJAutoProxyCreator object.

In our case, the object is to be woven into PowerServiceImpl notification of the target object, then we tracking to instantiate objects and create AOP proxy process PowerServiceImpl object.

Track subsection 4, AbstractApplicationContext.refresh () method finishBeanFactoryInitialization (beanFactory); Code (PowerServiceImpl proxy object belonging to the non-load delay, so in this example of the complete line of code inside)

Because AOP proxy creation, is achieved when SpringIOC container initialization, create code to find PowerServiceImpl in order to facilitate the AOP proxy object, we AnnotationConfigApplicationContext ctx in test01 method TestAOP's a = new AnnotationConfigApplicationContext (ConfigAOP.class); on the code, Add a debug, the manner in debug, follow the code, after the following:

AnnotationConfigApplicationContext.<init>(Class<?>...) line: 88
->AbstractApplicationContext.refresh() line: 550
->AbstractApplicationContext.finishBeanFactoryInitialization(ConfigurableListableBeanFactory) line: 869
->DefaultListableBeanFactory.preInstantiateSingletons() line: 728
1
2
3
4
5
6
7
DefaultListableBeanFactory.

Code block's internal preInstantiateSingletons () method is as follows:

if (this.logger.isDebugEnabled()) {

this.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.

List beanNames = new ArrayList<>(this.beanDefinitionNames);

Examples of a singleton object // all non-delay-loaded trigger

for (String beanName: beanNames) {

RootBeanDefinition BD = getMergedLocalBeanDefinition (beanName);

if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {

if (isFactoryBean(beanName)) {

Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);

if (bean instanceof FactoryBean) {

final FactoryBean<?> factory = (FactoryBean<?>) bean;

boolean isEagerInit;

if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {

isEagerInit = AccessController.doPrivileged((PrivilegedAction)

((SmartFactoryBean<?>) factory)::isEagerInit,

getAccessControlContext());

}

else {

isEagerInit = (factory instanceof SmartFactoryBean &&

((SmartFactoryBean<?>) factory).isEagerInit());

}

if (isEagerInit) {

getBean (beanName); ①

}

}

}

else {

getBean (beanName);

}

}

}

// trigger callback method after all of the corresponding bean initialization

for (String beanName: beanNames) {

Object singletonInstance = getSingleton(beanName);

if (singletonInstance instanceof SmartInitializingSingleton) {

final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;

if (System.getSecurityManager() != null) {

AccessController.doPrivileged((PrivilegedAction) () -> {

smartSingleton.afterSingletonsInstantiated();

return null;

}, getAccessControlContext());

}

else {

smartSingleton.afterSingletonsInstantiated();

}

}

}

The above code is mainly to do two things: a singleton object is an instance of the loading of all non-delay; a callback method is invoked after the instantiation of the object. Examples of the process for all objects are in the code above, the red labeled statement ①getBean (beanName) completed.

In order to understand the process of creating AOP proxy object, we need (beanName) ① in getBean; adding a debug breakpoint. Taking into account each object will enter this breakpoint created object, and we only care about PowerServiceImpl objects and the corresponding creation of AOP proxy object, so we can break above getBean () method, plus conditions. So that only qualifying time, it will stop at the breakpoint, to help us debug into it.

Add a conditional breakpoint in the following way:

1) In the getBean () line of the previous code, double-click Add a breakpoint (position is very important, as shown below note)

2) Right-click on the breakpoint and select Breakpoint Properties menu option ...

3) Click Breakpoint Properties ... option, select the Settings page, select the conditional options, input conditions colleagues condition statement in the input box. As shown below:

4) Click the OK button to clear another breakpoint () leaving only plus of the current conditional breakpoints), re-debug test01 method of operation TestAOP

Starting preceded conditional breakpoint, and gradually into debug, debug line as follows (for the first time might debug the following reference, to determine the position of the object created AOP, and then back to understand the logic of each process relates to a method of Process):

DefaultListableBeanFactory.preInstantiateSingletons() line: 760

->AbstractBeanFactory.getBean(String) line: 199
->AbstractBeanFactory.doGetBean(String, Class<T>, Object[], boolean) line: 315
->DefaultSingletonBeanRegistry.getSingleton(String, ObjectFactory<?>) line: 228
->AbstractBeanFactory.lambda$doGetBean$0(String, RootBeanDefinition, Object[]) line: 317
->AbstractAutowireCapableBeanFactory.createBean(String, RootBeanDefinition, Object[]) line: 501
->AbstractAutowireCapableBeanFactory.doCreateBean(...) line: 579
->AbstractAutowireCapableBeanFactory.initializeBean(...) line: 1706
->AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(.) line: 436
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
At this point, entered the Spring container to create AOP proxy object to PowerServiceImpl process, when the previous analysis @EnableAspectJAutoProxy source, we know AspectJAutoProxyRegistrar class, has registered a AnnotationAwareAspectJAutoProxyCreator class, and also preliminary tell you, Spring in the initialization container, based on need, use objects of that class to create AOP proxy object, completion notification to weave into the target entry point method. The operation in AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization (.) To complete the process.

(.) We see AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization method inside the source code is as follows:

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)

throws BeansException {

Object result = existingBean;

for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { ①

Object current = beanProcessor.postProcessAfterInitialization(result, beanName);②

if (current == null) {

return result;

}

result = current;

}

return result;

}

By reading the source code above, we can understand that the code is there to obtain all registered BeanPostProcessor (Bean post-processors) container, call the method for each cycle of postProcessAfterInitialization BeanPostProcessor (Bean post-processors), the current processing a target object (the object corresponding to the beanName). Select the code above ① line getBeanPostProcessors () part of the code, click the right mouse button and select Wath option, as shown:

Click the Watch option, enter the Debug window Expression view, you can see getBeanPostProcessors () method can get to all Bean postprocessor will traverse the call, in which the fourth is AnnotationAwareAspectJAutoProxyCreator, as shown below:

We cycle to the fourth post-processor, continue to debug in, such as:

AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(Object, String) line: 437

->AnnotationAwareAspectJAutoProxyCreator(AbstractAutoProxyCreator).postProcessAfterInitialization(…) line: 304

-> AnnotationAwareAspectJAutoProxyCreator (AbstractAutoProxyCreator) .wrapIfNecessary (... ...) Line: 340.
. 1
in wrapIfNecessary (...) method, the key code are as follows:

// Get all notifications to be woven into the entry point of the target object beanName

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); ①

if (specificInterceptors != DO_NOT_PROXY) {

this.advisedBeans.put(cacheKey, Boolean.TRUE);

// Create a proxy object

Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); ②

this.proxyTypes.put(cacheKey, proxy.getClass());

return proxy;

}

Wherein ① to obtain the code is woven into all notifications (blocking object) of the target entry point, we view the Debug mode variable values, to see all objects specificInterceptors interceptors in FIG:

A total of five notification object, in addition to the first default notice the object, the remaining four, are we then LogServiceImpl class, after notification of a useful marker notes notification object, namely @ Before, @ After, @ AfterReturning and @ AfterThrowing, in the figure above, it marked @AfterThrowing critical information.

Actually creating AOP proxy object, completion notification woven into the action, in ② lines of code, then we continue to go from ② start Debug, processes such as:

AbstractAutoProxyCreator.wrapIfNecessary(Object, String, Object) line: 356

->AbstractAutoProxyCreator.createProxy(Class<?>, String, Object[], TargetSource) line: 473

-> ProxyFactory.getProxy (ClassLoader) Line: 110
-> ProxyFactory (ProxyCreatorSupport) .createAopProxy () Line: 105
. 1
2
. 3
in ProxyCreatorSupport.createAopProxy () method, there are created conditions for ProxyFactory AOP was determined (for example, in @EnableAspectJAutoProxy annotation, if there is set to true proxyTargetClass property, etc.), decided to use CGLIB or JDK create AOP proxy object. Specific processes, please see createAopProxy () method and the source code comments noon, such as:

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)) { ①

// return a proxy object dynamically generated based on JDK

return new JdkDynamicAopProxy(config); ②

}

// return a proxy object dynamically generated based CGLIB

return new ObjenesisCglibAopProxy(config); ③

}

else {

// return a proxy object dynamically generated based on JDK

return new JdkDynamicAopProxy(config); ④

}

Our current PowerServiceImpl object-oriented programming interface, and there is no statement in @EnableAspectJAutoProxy annotation attributes, the current code will execute ④ lines of code, we continue to go in Debug, routes such as:

DefaultAopProxyFactory.createAopProxy(AdvisedSupport) line: 63

->ProxyFactory(ProxyCreatorSupport).createAopProxy() line: 105

-> ProxyFactory.getProxy (ClassLoader) Line: 110
-> JdkDynamicAopProxy.getProxy (ClassLoader) Line: 123
. 1
2
. 3
this time into the inside java.lang.reflect.Proxy JDK classes, created a dynamic objects SpringAOP ( AOP proxy object), we found the Spring AnnotationAwareAspectJAutoProxyCreator components used to complete the process of creating AOP proxy object.

06

to sum up

Risk by front and tracking source code, the following conclusions can be drawn

1) By adding the above configuration class @EnableAspectJAutoProxy annotation, annotation notify the AspectJ Spring container support, to achieve AOP oriented programming.

2) using @ Aspect, @ Pointcut, @ Before, @ After, @ AfterReturning, @ AfterThrowing and @Arount notes, completed section of the declaration that the starting point of the statement and a variety of notification.

3) Spring container, by AnnotationAwareAspectJAutoProxyCreator object, the target object after initialization, using the notification mechanism BeanPostProcessor rear complete AOP target object to create objects.

Internal 4) AnnotationAwareAspectJAutoProxyCreator object is encapsulated and JDK CGlib two techniques, the dynamic proxy object created.

5) Spring inside, using JDK or CGLIB, you can set proxyTargetClass attribute specifies @EnableAspectJAutoProxy can also be judged by Spring's own, whether the target object class implements an interface, it implements the interface, use JDK, otherwise use CGLIB.

Like the author of this article can give a point like, look, will share Java-related articles every day! There are benefits presented from time to time, including the consolidation of learning materials, interview questions, such as source code ~ ~

Guess you like

Origin blog.51cto.com/14440597/2421569