

Spring源码核心剖析 - 京东云技术团队
source link: https://www.cnblogs.com/jingdongkeji/p/17495777.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

SpringAOP作为Spring最核心的能力之一,其重要性不言而喻。然后需要知道的是AOP并不只是Spring特有的功能,而是一种思想,一种通用的功能。而SpringAOP只是在AOP的基础上将能力集成到SpringIOC中,使其作为bean的一种,从而我们能够很方便的进行使用。
一、SpringAOP的使用方式
1.1 使用场景
当我们在日常业务开发中,例如有些功能模块是通用的(日志、权限等),或者我们需要在某些功能前后去做一些增强,例如在某些方法执行后发送一条mq消息等。
如果我们将这些通用模块代码与业务代码放在一块,那么每个业务代码都要写这些通用模块,维护成本与耦合情况都十分严重。
因此,我们可以将此模块抽象出来,就有了”切面“的概念。
1.2 常用方式
AOP的使用方式相对比较简单,首先我们需要完成业务代码
@Service
public class AopDemo implements AopInterface{
public Student start(String name) {
System.out.println("执行业务逻辑代码.....");
return new Student(name);
}
}
业务逻辑比较简单,接收一个name参数。
接下来我们需要创建其对应的切面
//将该切面加入spring容器
@Service
//声明该类为一个切面
@Aspect
class AopAspect {
//声明要进行代理的方法
@Pointcut("execution(* com.example.demo.aop.AopInterface.start(..))")
public void startAspect() {
}
//在方法执行之前的逻辑
@Before(value = "startAspect()")
public void beforeAspect() {
System.out.println("业务逻辑前代码.....");
}
//在方法执行之后的逻辑
@After(value = "startAspect()")
public void afterAspect() {
System.out.println("业务逻辑后代码.....");
}
//围绕方法前后的逻辑
@Around("startAspect()")
public Object aroundAspect(ProceedingJoinPoint point) throws Throwable {
Object[] requestParams = point.getArgs();
String name = requestParams[0].toString();
System.out.println("传入参数:" + name);
requestParams[0] = "bob";
return point.proceed(requestParams);
}
}
可以看到,首先需要我们指明要代理的对象及方法,然后根据需要选择不同的注解即可实现代理对象。
传入参数:tom
业务逻辑前代码.....
执行业务逻辑代码.....
业务逻辑后代码.....
二、SpringAOP源码解析
2.1 被代理对象的开始initializeBean
根据上面的使用情况,我们知道只需要声明对应的注解即可,不需要其他额外的配置,然后我们获得的bean对象就已经是被代理的了,那么我们可以推断代理对象的过程一定是发生在bean创建的过程的。
我们回顾一下创建bean的流程
- 实例化bean
- 初始化bean
只有第三步初始化bean的时候才会有机会进行代理。
找到对应的代码位置:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//前置处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
//...
try {
//对象的初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
if (mbd == null || !mbd.isSynthetic()) {
//后置处理器,AOP开始的地方
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
2.2 后置处理器applyBeanPostProcessorsAfterInitialization
后置处理器会执行那些实现了后置处理器接口的代码:
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//获取所有的后置处理器
for (BeanPostProcessor processor : getBeanPostProcessors()) {
//实现其要执行的方法
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
而AOP的后置处理器就是其中的一个: AbstractAutoProxyCreator
其对应的方法为(以下代码不为同一个类,而是对应的执行顺序):
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
//执行到下面方法
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 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));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
protected Object createProxy(Class beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
//获取advisors
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// Use original ClassLoader if bean class not locally loaded in overriding class loader
ClassLoader classLoader = getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
}
//通过代理工厂创建代理对象
return proxyFactory.getProxy(classLoader);
}
public Object getProxy(@Nullable ClassLoader classLoader) {
//首先获取对应的代理
return createAopProxy().getProxy(classLoader);
}
//该方法根据要被代理的类选择使用jdk代理还是cglib代理
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!NativeDetector.inNativeImage() &&
(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
Class targetClass = config.getTargetClass();
//如果被代理的类是一个接口则使用jdk代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
//否则使用cglib代理
return new ObjenesisCglibAopProxy(config);
}
else {
//根据配置选择强制使用jdk代理
return new JdkDynamicAopProxy(config);
}
}
我们知道,代理方式有jdk动态代理与cglib动态代理两种方式,而我们一个bean使用那种代理方式则由上述的方法决定。
至此,我们已经确定了使用那种代理方式获取代理对象。
2.3 获取代理对象
从上文中,我们已经确定了选用何种方式构建代理对象。接下来就是通过不同的方式是如何获取代理对象的。
看懂本章需要实现了解jdk动态代理或者cglib动态代理的方式。
2.3.1 JDK代理
首先在获取代理对象时选择 JdkDynamicAopProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
//这里通过反射创建代理对象
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
当被代理对象执行被代理的方法时,会进入到此方法。(jdk动态代理的概念)
JDK通过反射创建对象,效率上来说相对低一些。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
// 获取被代理对象的所有切入点
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 如果调用链路为空说明没有需要执行的切入点,直接执行对应的方法即可
if (chain.isEmpty()) {
// 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 = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 如果有切入点的话则按照切入点顺序开始执行
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
return retVal;
}
}
invocation.proceed();这个方法就是通过递归的方式执行所有的调用链路。
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// 继续执行
return proceed();
}
}
else {
// 如果调用链路还持续的话,下一个方法仍会调用proceed()
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
2.3.2 cglib代理
public Object getProxy(@Nullable ClassLoader classLoader) {
try {
//配置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(new ClassLoaderAwareGeneratorStrategy(classLoader));
//1.获取回调函数,对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法
Callback[] callbacks = getCallbacks(rootClass);
Class[] types = new Class[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);
//2.创建代理对象
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);
}
}
可以看到我们在创建代理对象前会先获取代理对象的所有回调函数:
首先可以看到我们一共有7个回调方法,其中第一个为AOP相关的方法,其他的为spring相关。
在第一个对调对象中持有的 advised 对象中有 advisors 属性,就是对应我们的代理类中四个切片,@Before等等。
然后我们看一下 createProxyClassAndInstance()都做了什么。
//CglibAopProxy类的创建代理对象方法
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
enhancer.setInterceptDuringConstruction(false);
enhancer.setCallbacks(callbacks);
return (this.constructorArgs != null && this.constructorArgTypes != null ?
enhancer.create(this.constructorArgTypes, this.constructorArgs) :
enhancer.create());
}
//ObjenesisCglibAopProxy继承了CglibAopProxy类,并覆写了其方法
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
Class proxyClass = enhancer.createClass();
Object proxyInstance = null;
//1.尝试使用objenesis创建对象
if (objenesis.isWorthTrying()) {
try {
proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
}
catch (Throwable ex) {
logger.debug("Unable to instantiate proxy using Objenesis, " +
"falling back to regular proxy construction", ex);
}
}
//2.根据commit的提交记录发现,objenesis有可能创建对象失败,如果失败的话则选用放射的方式创建对象
if (proxyInstance == null) {
// Regular instantiation via default constructor...
try {
Constructor ctor = (this.constructorArgs != null ?
proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
proxyClass.getDeclaredConstructor());
ReflectionUtils.makeAccessible(ctor);
proxyInstance = (this.constructorArgs != null ?
ctor.newInstance(this.constructorArgs) : ctor.newInstance());
}
catch (Throwable ex) {
throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
"and regular proxy instantiation via default constructor fails as well", ex);
}
}
//
((Factory) proxyInstance).setCallbacks(callbacks);
return proxyInstance;
}
2.3.3 cglib
此处有个遇到的问题,当我在debug的时候,发现怎么都进不去 createProxyClassAndInstance(),百思不得其解,然后看到IDEA旁边有一个向下的箭头,代表该方法可能其子类被覆写了。然后在其子类处打断点果然发现是其子类的实现。
此处在2.2中也可看到:
可以看到返回的是其子类的对象,而不是CglibAopProxy本身的对象。
作者:京东科技 韩国凯
来源:京东云开发者社区
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK