转载

动态代理以及对应Spring中AOP源码分析

AOP(面向切面编程)在Spring中是被广泛应用的(例如日志,事务,权限等),而它的基本原理便是动态代理。

我们知道动态代理有两种:基于JDK的动态代理以及基于CGlib动态代理。以下是两种动态代理的实现方式:

//JDK动态代理

public class JDKProxy implements InvocationHandler {

private Object object;// 被代理人

//这里的目标类型为Object,则可以接受任意一种参数作为被代理类,实现了动态代理。但是要注意下面的newProxyInstance()中的参数

public Object getInstance(Object object) {

this.object = object;

//与cglib的区别在于这里构建代理对象的时候需要传入被代理对象的接口对象,第二个参数。而cglib不需要被代理对象实现任何接口即可   

return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);

}

//代理对象真正调用的方法

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

System.out.println("doSomething---------start");

method.invoke(object, args);

System.out.println("doSomething---------end");

return null;

}

}

//CGlib动态代理

public class CglibProxy implements MethodInterceptor {

private Object targetObject;

// 这里的目标类型为Object,则可以接受任意一种参数作为被代理类,实现了动态代理

public Object getInstance(Object target) {

this.targetObject = target;

Enhancer enhancer = new Enhancer();

enhancer.setSuperclass(target.getClass());

enhancer.setCallback(this);

//注意该处代理的创建过程

Object proxyObj = enhancer.create();

return proxyObj;// 返回代理对象

}

//代理对象真正调用的方法

@Override

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

Object obj = null;

System.out.println("doSomething---------start");

obj = method.invoke(targetObject, args);

System.out.println("doSomething---------end");

return obj;

}

}

具体两种动态代理的差异在网上有很多各个方面的比较,在这里我就不再赘述。下面我再说说在Spring 5.0.3.RELEASE中实现AOP的原理(我的github中也有详细的源码注释)。

在注解版的Spring AOP当中我们会有如下的代码配置,其中@EnableAspectJAutoProxy便是开启AOP支持的关键。

@EnableAspectJAutoProxy //开启基于注解的AOP模式

@Configuration

@ComponentScan(value = {"com.aop"})

public class AnnotationAopConfig {

@Bean("student")

public Student getStudent() { //把我们普通的Java Bean定义出来交给IOC容器管理

return new Student();

}

@Bean

public LogAspect getLogAspect() { //定义切面类

return new LogAspect();

}

}

我们跟踪一下@EnableAspectJAutoProxy的源码来看看它的定义,会发现它利用@Import导入了AspectJAutoProxyRegistrar.class组件:代码块一

由AspectJAutoProxyRegistrar.Class的定义可知其实现了ImportBeanDefinitionRegistrar接口,所以在IOC容器初始化的时候会调用该类的registerBeanDefinitions方法。通过观察该方法实现,我们可以看到一行关键的代码AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);:代码块二

这行代码中所需要注册的到底是什么东西呢?我们进一步一探究竟。在持续跟入代码的过程中我们可以找到这么一块代码:return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);:代码块三

观察源码可以得知,该方法会将AnnotationAwareAspectJAutoProxyCreator类封装为一个RootBeanDefinition然后添加到BeanDefinition的注册类当中以AUTO_PROXY_CREATOR_BEAN_NAME。我们也可以找到关于AUTO_PROXY_CREATOR_BEAN_NAME的定义:代码块四

我们再分析一下AnnotationAwareAspectJAutoProxyCreator.Class的源码,看看此类到底有何特别之处。观察源码我们可以发现AnnotationAwareAspectJAutoProxyCreator是BeanPostPrcsessor的子类:代码块五

/**********************代码块一***********************/

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Import(AspectJAutoProxyRegistrar.class) //导入AspectJAutoProxyRegistrar组件

public @interface EnableAspectJAutoProxy {

/**********************代码块二***********************/

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

@Override

public void registerBeanDefinitions(

AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); //如果需要的话注册AspectJAnnotationAutoProxy

/**********************代码块三***********************/

@Nullable

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,

@Nullable Object source) {

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

}

/**********************代码块四***********************/

/**

* The bean name of the internally managed auto-proxy creator.

*/

public static final String AUTO_PROXY_CREATOR_BEAN_NAME = "org.springframework.aop.config.internalAutoProxyCreator";

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry,

@Nullable Object source) {

Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {

BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);

if (!cls.getName().equals(apcDefinition.getBeanClassName())) {

int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());

int requiredPriority = findPriorityForClass(cls);

if (currentPriority < requiredPriority) {

apcDefinition.setBeanClassName(cls.getName());

}

}

return null;

}

RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);

beanDefinition.setSource(source);

beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);

beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);//注册

return beanDefinition;

}

/**********************代码块五***********************/

AnnotationAwareAspectJAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator

extends AspectJAwareAdvisorAutoProxyCreator

extends AbstractAdvisorAutoProxyCreator

extends AbstractAutoProxyCreator

extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware

extends ...InstantiationAwareBeanPostProcessor Ordered

extends BeanPostProcessor

从以上代码,我们可以知道@EnableAspectJAutoProxy大概做了这么一件事:将AnnotationAwareAspectJAutoProxyCreator.Class以名为“org.springframework.aop.config.internalAutoProxyCreator”的方式完成注册BeanDefinition的操作。

然后我们再看看这块内容对Spring容器启动过程的影响。

我们以下面的代码为入口进行分析:代码块一

我们进入IOC容器初始化过程看看对于进行了切面操作的类来说经历了哪些操作,通过断点我们可以跟踪到此代码处:PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);这里是实例化各种BeanPostProcessor,并将其实例存放在BeanFactory当中:代码块二(当中代码我挑出重要的部分。更加详细的Spring源码说明,请关注我的github)。

注册了BeanPostProcessor的实例,我们看看普通Bean对象的创建。跟踪源码可知:通过finishBeanFactoryInitialization等一系列方法的调用到getBean(beanName);方法之中,在getBean(beanName);后续的调用之中又经过了查询缓存,实例化依赖等一系列操作来到了createBean这个方法当中,我们可以通过代码详细分析其处理。我们可以找到Object beanInstance = doCreateBean(beanName, mbdToUse, args); 获取Bean实例的地方。 再跟进去看它的实现:代码块三

我们现在观察doCreateBean(beanName, mbdToUse, args); 源码,其中实现了移除缓存、创建实例、初始化实例等一系列操作,其中在exposedObject = initializeBean(beanName, exposedObject, mbd);中变有我们需要的关键信息。:代码块四

initializeBean(beanName, exposedObject, mbd);这个方法里面有applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);和applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);两个方法的调用。这里面的原理是获取所有的beanPostProcessors遍历调用其postProcessBeforeInitialization和postProcessAfterInitialization方法。这里我就不过多的赘述了。调试代码我们可以发现后续的调用链如下AbstractAutoProxyCreator#postProcessAfterInitialization-->AbstractAutoProxyCreator#wrapIfNecessary。在这里我们就可以判断其是否拥有增强器来创建代理对象,我们可以通过下面代码来观察其逻辑(增强器便是代理对象的各个方法封装起来的对象):代码块五

进入代理构建入口Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));以下便是通过默认的GClib来进行对象的一个封装。其代理封装的对象如下:代码块六

/**********************代码块一***********************/

@Test

public void test3() {

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationAopConfig.class); //初始化IOC容器

String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();

Student student = (Student) applicationContext.getBean("student");//从容器中获取对象

student.innerMethod(); //进行方法调用

applicationContext.close();

}

/**********************代码块二***********************/

public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

/**

* IOC:stepA6-1 获取到所有已经定义了的,需要创建实例的所有实现BeanPostProcessor的类

* org.springframework.context.annotation.internalAutowiredAnnotationProcessor

* org.springframework.context.annotation.internalRequiredAnnotationProcessor

* org.springframework.aop.config.internalAutoProxyCreator

*/

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

....

/**

* 分离实现了PriorityOrdered、Ordered和rest接口的BeanPostProcessors

* 按顺序注册BeanPostProcessors

*/

List<String> orderedPostProcessorNames = new ArrayList<>();

List<String> nonOrderedPostProcessorNames = new ArrayList<>();

for (String ppName : postProcessorNames) {

if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { //如果是PriorityOrdered的子类

....

}

else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { //AOP 匹配internalAutoProxyCreator,添加到orderedPostProcessorNames集合当中

orderedPostProcessorNames.add(ppName);

}

else {

nonOrderedPostProcessorNames.add(ppName);

}

}

// 首先, 注册实现PriorityOrdered接口的BeanPostProcessors

sortPostProcessors(priorityOrderedPostProcessors, beanFactory);

registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

// Next, register the BeanPostProcessors that implement Ordered.

List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();

for (String ppName : orderedPostProcessorNames) {

BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); //实例化internalAutoProxyCreator

orderedPostProcessors.add(pp);

if (pp instanceof MergedBeanDefinitionPostProcessor) {

internalPostProcessors.add(pp);//将internalAutoProxyCreator实例放进去

}

}

sortPostProcessors(orderedPostProcessors, beanFactory);

registerBeanPostProcessors(beanFactory, orderedPostProcessors); //将BeanPostProcessor注册到BeanFactory

....

}

/**********************代码块三***********************/

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

throws BeanCreationException {

....

try {

// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.

//IOC:stepA10 给BeanPostProcessor一个机会返回一个代理实例代替Bean实例

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

if (bean != null) {

return bean;

}

}

catch (Throwable ex) {

throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,

"BeanPostProcessor before instantiation of bean failed", ex);

}

try {

Object beanInstance = doCreateBean(beanName, mbdToUse, args);  //创建Bean实例

if (logger.isDebugEnabled()) {

logger.debug("Finished creating instance of bean '" + beanName + "'");

}

return beanInstance;

}

catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {

....

}

}

/**********************代码块四***********************/

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)

throws BeanCreationException {

// Instantiate the bean.

BeanWrapper instanceWrapper = null;

if (mbd.isSingleton()) { //如果是单例,从factoryBean实例缓存中移除

instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);

}

if (instanceWrapper == null) {

instanceWrapper = createBeanInstance(beanName, mbd, args);//创建实例

}

....

//缓存bean解决循环引用

....

// Initialize the bean instance.

//初始化bean实例

Object exposedObject = bean;

try {

populateBean(beanName, mbd, instanceWrapper); //为Bean的属性赋值

exposedObject = initializeBean(beanName, exposedObject, mbd); //初始化对象

}

....

}

/**********************代码块五***********************/

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.

//如果有增强器的话就创建代理

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

if (specificInterceptors != DO_NOT_PROXY) {

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

Object proxy = createProxy(

bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));//创建AOP代理对象

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

return proxy;

}

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

return bean;

}

/**********************代码块六***********************/

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

private final AdvisedSupport advised;

public DynamicAdvisedInterceptor(AdvisedSupport advised) {

this.advised = advised;

}

@Override

@Nullable

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

Object oldProxy = null;

boolean setProxyContext = false;

Object target = null;

TargetSource targetSource = this.advised.getTargetSource();

try {

if (this.advised.exposeProxy) {

// Make invocation available if necessary.

oldProxy = AopContext.setCurrentProxy(proxy);

setProxyContext = true;

}

// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...

target = targetSource.getTarget();

Class<?> targetClass = (target != null ? target.getClass() : null);

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);//根据将要执行的目标方法获取拦截器链

Object retVal;

// Check whether we only have one InvokerInterceptor: that is,

// no real advice, but just reflective invocation of the target.

if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {

// We can skip creating a MethodInvocation: just invoke the target directly.

// Note that the final invoker must be an InvokerInterceptor, so we know

// it does nothing but a reflective operation on the target, and no hot

// swapping or fancy proxying.

Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);

retVal = methodProxy.invoke(target, argsToUse);

}

else {

// We need to create a method invocation...

retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();//执行拦截器链

}

retVal = processReturnType(proxy, target, method, retVal);

return retVal;

}

finally {

if (target != null && !targetSource.isStatic()) {

targetSource.releaseTarget(target);

}

if (setProxyContext) {

// Restore old proxy.

AopContext.setCurrentProxy(oldProxy);

}

}

}

}

下面我们可以通过调试代码的方式来探究拦截器的调用。在这里拦截器是通过链式调用的方法按照顺序依次执行,我们可以通过时序图来很好的发现其调用逻辑。

好了,不知道通过源码阅读大家有没有对Spring AOP有了一个全新的认识呢?有任何疑问欢迎留言喔~

Linux公社的RSS地址 : https://www.linuxidc.com/rssFeed.aspx

本文永久更新链接地址: https://www.linuxidc.com/Linux/2019-08/160264.htm

原文  https://www.linuxidc.com/Linux/2019-08/160264.htm
正文到此结束
Loading...