Spring AOP底层实现分析

蔚落 2022-05-10 02:36 282阅读 0赞

Spring AOP代理对象的生成

Spring提供了两种方式来生成代理对象: JdkProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理。

![Image 1][]

aop.png

具体逻辑在 org.springframework.aop.framework.DefaultAopProxyFactory类中,源码如下:

  1. /**
  2. * Spring AOP代理工厂
  3. */
  4. public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
  5. @Override
  6. public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  7. if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
  8. Class<?> targetClass = config.getTargetClass();
  9. if (targetClass == null) {
  10. throw new AopConfigException("TargetSource cannot determine target class: " +
  11. "Either an interface or a target is required for proxy creation.");
  12. }
  13. //如果目标类是接口, 使用JDK动态代理来生成代理类及代理类实例对象
  14. if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
  15. return new JdkDynamicAopProxy(config);
  16. }
  17. //使用Cglib生成代理类及代理类实例对象
  18. return new ObjenesisCglibAopProxy(config);
  19. }
  20. else {
  21. return new JdkDynamicAopProxy(config);
  22. }
  23. }
  24. private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
  25. Class<?>[] ifcs = config.getProxiedInterfaces();
  26. return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
  27. }
  28. }

JDK动态代理技术生成代理类及实例对象

下面我们来研究一下Spring如何使用JDK来生成代理对象,具体的生成代码放在org.springframework.aop.framework.JdkDynamicAopProxy 这个类中,直接上相关代码:

  1. /**
  2. * JDK动态代理实现类
  3. */
  4. final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
  5. /** use serialVersionUID from Spring 1.2 for interoperability */
  6. private static final long serialVersionUID = 5531744639992436476L;
  7. /** We use a static Log to avoid serialization issues */
  8. private static final Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);
  9. /** Config used to configure this proxy */
  10. private final AdvisedSupport advised;
  11. /**
  12. * Is the {@link #equals} method defined on the proxied interfaces?
  13. */
  14. private boolean equalsDefined;
  15. /**
  16. * Is the {@link #hashCode} method defined on the proxied interfaces?
  17. */
  18. private boolean hashCodeDefined;
  19. /**
  20. * Construct a new JdkDynamicAopProxy for the given AOP configuration.
  21. * @param config the AOP configuration as AdvisedSupport object
  22. * @throws AopConfigException if the config is invalid. We try to throw an informative
  23. * exception in this case, rather than let a mysterious failure happen later.
  24. */
  25. public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
  26. Assert.notNull(config, "AdvisedSupport must not be null");
  27. if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
  28. throw new AopConfigException("No advisors and no TargetSource specified");
  29. }
  30. this.advised = config;
  31. }
  32. /**
  33. * 使用JDK动态代理生成代理类
  34. */
  35. @Override
  36. public Object getProxy() {
  37. return getProxy(ClassUtils.getDefaultClassLoader());
  38. }
  39. @Override
  40. public Object getProxy(ClassLoader classLoader) {
  41. if (logger.isDebugEnabled()) {
  42. logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
  43. }
  44. Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
  45. findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
  46. return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
  47. }
  48. /**
  49. * Finds any {@link #equals} or {@link #hashCode} method that may be defined
  50. * on the supplied set of interfaces.
  51. * @param proxiedInterfaces the interfaces to introspect
  52. */
  53. private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
  54. for (Class<?> proxiedInterface : proxiedInterfaces) {
  55. Method[] methods = proxiedInterface.getDeclaredMethods();
  56. for (Method method : methods) {
  57. if (AopUtils.isEqualsMethod(method)) {
  58. this.equalsDefined = true;
  59. }
  60. if (AopUtils.isHashCodeMethod(method)) {
  61. this.hashCodeDefined = true;
  62. }
  63. if (this.equalsDefined && this.hashCodeDefined) {
  64. return;
  65. }
  66. }
  67. }
  68. }
  69. }

JdkDynamicAopProxy 同时实现了AopProxy和InvocationHandler接口,InvocationHandler是JDK动态代理的核心,生成的代理对象的方法调用都会委托到InvocationHandler.invoke()方法。下面我们就通过分析这个类中实现的invoke()方法来具体看下Spring AOP是如何织入切面的。

  1. @Override
  2. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  3. MethodInvocation invocation;
  4. Object oldProxy = null;
  5. boolean setProxyContext = false;
  6. TargetSource targetSource = this.advised.targetSource;
  7. Class<?> targetClass = null;
  8. Object target = null;
  9. try {
  10. if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { //目标类没有实现eqauls()方法
  11. // The target does not implement the equals(Object) method itself.
  12. return equals(args[0]);
  13. }
  14. else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { //目标类没有实现hashCode()方法
  15. // The target does not implement the hashCode() method itself.
  16. return hashCode();
  17. }
  18. else if (method.getDeclaringClass() == DecoratingProxy.class) {
  19. // There is only getDecoratedClass() declared -> dispatch to proxy config.
  20. return AopProxyUtils.ultimateTargetClass(this.advised);
  21. }
  22. else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
  23. method.getDeclaringClass().isAssignableFrom(Advised.class)) {
  24. // Service invocations on ProxyConfig with the proxy config...
  25. return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
  26. }
  27. Object retVal;
  28. if (this.advised.exposeProxy) {
  29. // Make invocation available if necessary.
  30. oldProxy = AopContext.setCurrentProxy(proxy);
  31. setProxyContext = true;
  32. }
  33. // May be null. Get as late as possible to minimize the time we "own" the target,
  34. // in case it comes from a pool.
  35. target = targetSource.getTarget();
  36. if (target != null) {
  37. targetClass = target.getClass();
  38. }
  39. // Get the interception chain for this method.
  40. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  41. // Check whether we have any advice. If we don't, we can fallback on direct
  42. // reflective invocation of the target, and avoid creating a MethodInvocation.
  43. if (chain.isEmpty()) {
  44. // We can skip creating a MethodInvocation: just invoke the target directly
  45. // Note that the final invoker must be an InvokerInterceptor so we know it does
  46. // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
  47. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
  48. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
  49. }
  50. else {
  51. // We need to create a method invocation...
  52. invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
  53. // Proceed to the joinpoint through the interceptor chain.
  54. retVal = invocation.proceed();
  55. }
  56. // Massage return value if necessary.
  57. Class<?> returnType = method.getReturnType();
  58. if (retVal != null && retVal == target &&
  59. returnType != Object.class && returnType.isInstance(proxy) &&
  60. !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
  61. // Special case: it returned "this" and the return type of the method
  62. // is type-compatible. Note that we can't help if the target sets
  63. // a reference to itself in another returned object.
  64. retVal = proxy;
  65. }
  66. else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
  67. throw new AopInvocationException(
  68. "Null return value from advice does not match primitive return type for: " + method);
  69. }
  70. return retVal;
  71. }
  72. finally {
  73. if (target != null && !targetSource.isStatic()) {
  74. // Must have come from TargetSource.
  75. targetSource.releaseTarget(target);
  76. }
  77. if (setProxyContext) {
  78. // Restore old proxy.
  79. AopContext.setCurrentProxy(oldProxy);
  80. }
  81. }
  82. }

主流程可以简述为:获取可以应用到此方法上的通知链(Interceptor Chain),如果有,则应用通知,并执行joinpoint;如果通知链为空,则直接反射执行joinpoint。

而这里的关键是通知链是如何获取的以及它又是如何执行的,下面逐一分析下。

首先,从上面的代码可以看到,通知链是通过AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice()这个方法来获取的,我们来看下这个方法的实现:

  1. public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
  2. MethodCacheKey cacheKey = new MethodCacheKey(method);
  3. List<Object> cached = this.methodCache.get(cacheKey);
  4. if (cached == null) {
  5. cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
  6. this, method, targetClass);
  7. this.methodCache.put(cacheKey, cached);
  8. }
  9. return cached;
  10. }

可以看到实际的获取工作其实是由org.springframework.aop.framework.AdvisorChainFactory的 getInterceptorsAndDynamicInterceptionAdvice()这个方法来完成的,获取到的结果会被缓存。
AdvisorChainFactory接口只有一个默认实现类 :DefaultAdvisorChainFactory,下面来分析下这个类的实现:

  1. package org.springframework.aop.framework;
  2. @SuppressWarnings("serial")
  3. public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {
  4. @Override
  5. public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
  6. Advised config, Method method, Class<?> targetClass) {
  7. // This is somewhat tricky... We have to process introductions first,
  8. // but we need to preserve order in the ultimate list.
  9. List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
  10. Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
  11. //查看是否包含IntroductionAdvisor
  12. boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
  13. //用于将Advisor转化成MethodInterceptor
  14. AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
  15. for (Advisor advisor : config.getAdvisors()) {
  16. if (advisor instanceof PointcutAdvisor) {
  17. // Add it conditionally.
  18. PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
  19. if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
  20. //将Advisor转化成Interceptor
  21. MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
  22. //检查当前advisor的pointcut是否可以匹配当前方法
  23. MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
  24. if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
  25. if (mm.isRuntime()) {
  26. // Creating a new object instance in the getInterceptors() method
  27. // isn't a problem as we normally cache created chains.
  28. for (MethodInterceptor interceptor : interceptors) {
  29. interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
  30. }
  31. }
  32. else {
  33. interceptorList.addAll(Arrays.asList(interceptors));
  34. }
  35. }
  36. }
  37. }
  38. else if (advisor instanceof IntroductionAdvisor) {
  39. IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
  40. if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
  41. Interceptor[] interceptors = registry.getInterceptors(advisor);
  42. interceptorList.addAll(Arrays.asList(interceptors));
  43. }
  44. }
  45. else {
  46. Interceptor[] interceptors = registry.getInterceptors(advisor);
  47. interceptorList.addAll(Arrays.asList(interceptors));
  48. }
  49. }
  50. return interceptorList;
  51. }
  52. /**
  53. * Determine whether the Advisors contain matching introductions.
  54. */
  55. private static boolean hasMatchingIntroductions(Advised config, Class<?> actualClass) {
  56. for (int i = 0; i < config.getAdvisors().length; i++) {
  57. Advisor advisor = config.getAdvisors()[i];
  58. if (advisor instanceof IntroductionAdvisor) {
  59. IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
  60. if (ia.getClassFilter().matches(actualClass)) {
  61. return true;
  62. }
  63. }
  64. }
  65. return false;
  66. }
  67. }

这个方法执行完成后,Advised中配置能够应用到连接点或者目标类的Advisor全部被转化成了MethodInterceptor.

接下来,回到 JdkDynamicAopProxy的 invoke方法中,如下:

  1. // 获取这个方法上的拦截器链
  2. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  3. if (chain.isEmpty()) {
  4. //直接调用
  5. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
  6. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
  7. }
  8. else {
  9. // 创建MethodInvocation
  10. invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
  11. // Proceed to the joinpoint through the interceptor chain.
  12. retVal = invocation.proceed();
  13. }

从这段代码可以看出,如果得到的拦截器链为空,则直接反射调用目标方法,否则创建ReflectiveMethodInvocation,调用其proceed方法,触发拦截器链的执行,来看下 ReflectiveMethodInvocation 的proceed() 方法源码:

  1. @Override
  2. public Object proceed() throws Throwable {
  3. // We start with an index of -1 and increment early.
  4. if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
  5. return invokeJoinpoint();
  6. }
  7. Object interceptorOrInterceptionAdvice =
  8. this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
  9. if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
  10. // Evaluate dynamic method matcher here: static part will already have
  11. // been evaluated and found to match.
  12. InterceptorAndDynamicMethodMatcher dm =
  13. (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
  14. if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
  15. return dm.interceptor.invoke(this);
  16. }
  17. else {
  18. // Dynamic matching failed.
  19. // Skip this interceptor and invoke the next in the chain.
  20. return proceed();
  21. }
  22. }
  23. else {
  24. // It's an interceptor, so we just invoke it: The pointcut will have
  25. // been evaluated statically before this object was constructed.
  26. return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
  27. }
  28. }
  29. /**
  30. * Invoke the joinpoint using reflection.
  31. * Subclasses can override this to use custom invocation.
  32. * @return the return value of the joinpoint
  33. * @throws Throwable if invoking the joinpoint resulted in an exception
  34. */
  35. protected Object invokeJoinpoint() throws Throwable {
  36. return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
  37. }

Cglib生成代理类及实例对象

接下来的分析会涉及到Cglib 使用,对Cglib不熟悉的同学,先看看 [Cglib Tutorial] (https://github.com/cglib/cglib/wiki/Tutorial)。

Spring AOP中使用Cglib生成动态代理的类是
org.springframework.aop.framework.ObjenesisCglibAopProxy ,它继承自 org.springframework.aop.framework.CglibAopProxy,我们首先来看看CglibAopProxy 的源码:

  1. /**
  2. * Cglib动态代理实现类
  3. */
  4. class CglibAopProxy implements AopProxy, Serializable {
  5. // Constants for CGLIB callback array indices
  6. private static final int AOP_PROXY = 0;
  7. private static final int INVOKE_TARGET = 1;
  8. private static final int NO_OVERRIDE = 2;
  9. private static final int DISPATCH_TARGET = 3;
  10. private static final int DISPATCH_ADVISED = 4;
  11. private static final int INVOKE_EQUALS = 5;
  12. private static final int INVOKE_HASHCODE = 6;
  13. /** Logger available to subclasses; static to optimize serialization */
  14. protected static final Log logger = LogFactory.getLog(CglibAopProxy.class);
  15. /** Keeps track of the Classes that we have validated for final methods */
  16. private static final Map<Class<?>, Boolean> validatedClasses = new WeakHashMap<Class<?>, Boolean>();
  17. /** The configuration used to configure this proxy */
  18. protected final AdvisedSupport advised;
  19. protected Object[] constructorArgs;
  20. protected Class<?>[] constructorArgTypes;
  21. /** Dispatcher used for methods on Advised */
  22. private final transient AdvisedDispatcher advisedDispatcher;
  23. private transient Map<String, Integer> fixedInterceptorMap;
  24. private transient int fixedInterceptorOffset;
  25. public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
  26. Assert.notNull(config, "AdvisedSupport must not be null");
  27. if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
  28. throw new AopConfigException("No advisors and no TargetSource specified");
  29. }
  30. this.advised = config;
  31. this.advisedDispatcher = new AdvisedDispatcher(this.advised);
  32. }
  33. @Override
  34. public Object getProxy() {
  35. return getProxy(null);
  36. }
  37. @Override
  38. public Object getProxy(ClassLoader classLoader) {
  39. if (logger.isDebugEnabled()) {
  40. logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
  41. }
  42. try {
  43. Class<?> rootClass = this.advised.getTargetClass();
  44. Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
  45. Class<?> proxySuperClass = rootClass;
  46. if (ClassUtils.isCglibProxyClass(rootClass)) {
  47. proxySuperClass = rootClass.getSuperclass();
  48. Class<?>[] additionalInterfaces = rootClass.getInterfaces();
  49. for (Class<?> additionalInterface : additionalInterfaces) {
  50. this.advised.addInterface(additionalInterface);
  51. }
  52. }
  53. // Validate the class, writing log messages as necessary.
  54. validateClassIfNecessary(proxySuperClass, classLoader);
  55. // Cglib Enhancer配置
  56. Enhancer enhancer = createEnhancer();
  57. if (classLoader != null) {
  58. enhancer.setClassLoader(classLoader);
  59. if (classLoader instanceof SmartClassLoader &&
  60. ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
  61. enhancer.setUseCache(false);
  62. }
  63. }
  64. enhancer.setSuperclass(proxySuperClass);
  65. enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
  66. enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
  67. enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
  68. // Cglib 动态代理核心
  69. Callback[] callbacks = getCallbacks(rootClass);
  70. Class<?>[] types = new Class<?>[callbacks.length];
  71. for (int x = 0; x < types.length; x++) {
  72. types[x] = callbacks[x].getClass();
  73. }
  74. // fixedInterceptorMap only populated at this point, after getCallbacks call above
  75. enhancer.setCallbackFilter(new ProxyCallbackFilter(
  76. this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
  77. enhancer.setCallbackTypes(types);
  78. // 生成动态代理类和代理类实例
  79. return createProxyClassAndInstance(enhancer, callbacks);
  80. }
  81. catch (CodeGenerationException ex) {
  82. throw new AopConfigException("Could not generate CGLIB subclass of class [" +
  83. this.advised.getTargetClass() + "]: " +
  84. "Common causes of this problem include using a final class or a non-visible class",
  85. ex);
  86. }
  87. catch (IllegalArgumentException ex) {
  88. throw new AopConfigException("Could not generate CGLIB subclass of class [" +
  89. this.advised.getTargetClass() + "]: " +
  90. "Common causes of this problem include using a final class or a non-visible class",
  91. ex);
  92. }
  93. catch (Exception ex) {
  94. // TargetSource.getTarget() failed
  95. throw new AopConfigException("Unexpected AOP exception", ex);
  96. }
  97. }
  98. protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
  99. enhancer.setInterceptDuringConstruction(false);
  100. //设置方法回调
  101. enhancer.setCallbacks(callbacks);
  102. return (this.constructorArgs != null ?
  103. enhancer.create(this.constructorArgTypes, this.constructorArgs) :
  104. enhancer.create());
  105. }
  106. }

CglibAopProxy 和 JdkDynamicAopProxy类一样 实现了 org.springframework.aop.framework.AopProxy接口。

既然使用Cglib来生成代理类,那么其生成的代理对象的方法调用都会委托到Callback,我们来看一下 getCallbacks() 方法,源码如下:

  1. private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
  2. // Parameters used for optimisation choices...
  3. boolean exposeProxy = this.advised.isExposeProxy();
  4. boolean isFrozen = this.advised.isFrozen();
  5. boolean isStatic = this.advised.getTargetSource().isStatic();
  6. // Choose an "aop" interceptor (used for AOP calls).
  7. Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
  8. // Choose a "straight to target" interceptor. (used for calls that are
  9. // unadvised but can return this). May be required to expose the proxy.
  10. Callback targetInterceptor;
  11. if (exposeProxy) {
  12. targetInterceptor = isStatic ?
  13. new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
  14. new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
  15. }
  16. else {
  17. targetInterceptor = isStatic ?
  18. new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
  19. new DynamicUnadvisedInterceptor(this.advised.getTargetSource());
  20. }
  21. // Choose a "direct to target" dispatcher (used for
  22. // unadvised calls to static targets that cannot return this).
  23. Callback targetDispatcher = isStatic ?
  24. new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();
  25. Callback[] mainCallbacks = new Callback[] {
  26. aopInterceptor, // for normal advice
  27. targetInterceptor, // invoke target without considering advice, if optimized
  28. new SerializableNoOp(), // no override for methods mapped to this
  29. targetDispatcher, this.advisedDispatcher,
  30. new EqualsInterceptor(this.advised),
  31. new HashCodeInterceptor(this.advised)
  32. };
  33. Callback[] callbacks;
  34. // If the target is a static one and the advice chain is frozen,
  35. // then we can make some optimisations by sending the AOP calls
  36. // direct to the target using the fixed chain for that method.
  37. if (isStatic && isFrozen) {
  38. Method[] methods = rootClass.getMethods();
  39. Callback[] fixedCallbacks = new Callback[methods.length];
  40. this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length);
  41. // TODO: small memory optimisation here (can skip creation for methods with no advice)
  42. for (int x = 0; x < methods.length; x++) {
  43. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
  44. fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
  45. chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
  46. this.fixedInterceptorMap.put(methods[x].toString(), x);
  47. }
  48. // Now copy both the callbacks from mainCallbacks
  49. // and fixedCallbacks into the callbacks array.
  50. callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
  51. System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
  52. System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
  53. this.fixedInterceptorOffset = mainCallbacks.length;
  54. }
  55. else {
  56. callbacks = mainCallbacks;
  57. }
  58. return callbacks;
  59. }

ObjenesisCglibAopProxy 类源码如下:

  1. class ObjenesisCglibAopProxy extends CglibAopProxy {
  2. private static final Log logger = LogFactory.getLog(ObjenesisCglibAopProxy.class);
  3. private static final SpringObjenesis objenesis = new SpringObjenesis();
  4. /**
  5. * Create a new ObjenesisCglibAopProxy for the given AOP configuration.
  6. * @param config the AOP configuration as AdvisedSupport object
  7. */
  8. public ObjenesisCglibAopProxy(AdvisedSupport config) {
  9. super(config);
  10. }
  11. @Override
  12. @SuppressWarnings("unchecked")
  13. protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
  14. Class<?> proxyClass = enhancer.createClass();
  15. Object proxyInstance = null;
  16. if (objenesis.isWorthTrying()) {
  17. try {
  18. proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
  19. }
  20. catch (Throwable ex) {
  21. logger.debug("Unable to instantiate proxy using Objenesis, " +
  22. "falling back to regular proxy construction", ex);
  23. }
  24. }
  25. if (proxyInstance == null) {
  26. // Regular instantiation via default constructor...
  27. try {
  28. proxyInstance = (this.constructorArgs != null ?
  29. proxyClass.getConstructor(this.constructorArgTypes).newInstance(this.constructorArgs) :
  30. proxyClass.newInstance());
  31. }
  32. catch (Throwable ex) {
  33. throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
  34. "and regular proxy instantiation via default constructor fails as well", ex);
  35. }
  36. }
  37. ((Factory) proxyInstance).setCallbacks(callbacks);
  38. return proxyInstance;
  39. }
  40. }

ObjenesisCglibAopProxy 重写了父类 CglibAopProxy 中的createProxyClassAndInstance方法,使用 Objenesis来生成代理类实例对象。

SpringObjenesis 源码如下:

  1. package org.springframework.objenesis;
  2. import org.springframework.core.SpringProperties;
  3. import org.springframework.objenesis.Objenesis;
  4. import org.springframework.objenesis.ObjenesisException;
  5. import org.springframework.objenesis.instantiator.ObjectInstantiator;
  6. import org.springframework.objenesis.strategy.InstantiatorStrategy;
  7. import org.springframework.objenesis.strategy.StdInstantiatorStrategy;
  8. import org.springframework.util.ConcurrentReferenceHashMap;
  9. public class SpringObjenesis implements Objenesis {
  10. public static final String IGNORE_OBJENESIS_PROPERTY_NAME = "spring.objenesis.ignore";
  11. private final InstantiatorStrategy strategy;
  12. private final ConcurrentReferenceHashMap<Class<?>, ObjectInstantiator<?>> cache;
  13. private volatile Boolean worthTrying;
  14. public SpringObjenesis() {
  15. this((InstantiatorStrategy)null);
  16. }
  17. public SpringObjenesis(InstantiatorStrategy strategy) {
  18. this.cache = new ConcurrentReferenceHashMap();
  19. this.strategy = (InstantiatorStrategy)(strategy != null?strategy:new StdInstantiatorStrategy());
  20. if(SpringProperties.getFlag("spring.objenesis.ignore")) {
  21. this.worthTrying = Boolean.FALSE;
  22. }
  23. }
  24. public boolean isWorthTrying() {
  25. return this.worthTrying != Boolean.FALSE;
  26. }
  27. public <T> T newInstance(Class<T> clazz, boolean useCache) {
  28. return !useCache?this.newInstantiatorOf(clazz).newInstance():this.getInstantiatorOf(clazz).newInstance();
  29. }
  30. public <T> T newInstance(Class<T> clazz) {
  31. return this.getInstantiatorOf(clazz).newInstance();
  32. }
  33. public <T> ObjectInstantiator<T> getInstantiatorOf(Class<T> clazz) {
  34. ObjectInstantiator instantiator = (ObjectInstantiator)this.cache.get(clazz);
  35. if(instantiator == null) {
  36. ObjectInstantiator newInstantiator = this.newInstantiatorOf(clazz);
  37. instantiator = (ObjectInstantiator)this.cache.putIfAbsent(clazz, newInstantiator);
  38. if(instantiator == null) {
  39. instantiator = newInstantiator;
  40. }
  41. }
  42. return instantiator;
  43. }
  44. protected <T> ObjectInstantiator<T> newInstantiatorOf(Class<T> clazz) {
  45. Boolean currentWorthTrying = this.worthTrying;
  46. try {
  47. ObjectInstantiator err = this.strategy.newInstantiatorOf(clazz);
  48. if(currentWorthTrying == null) {
  49. this.worthTrying = Boolean.TRUE;
  50. }
  51. return err;
  52. } catch (ObjenesisException var5) {
  53. if(currentWorthTrying == null) {
  54. Throwable cause = var5.getCause();
  55. if(cause instanceof ClassNotFoundException || cause instanceof IllegalAccessException) {
  56. this.worthTrying = Boolean.FALSE;
  57. }
  58. }
  59. throw var5;
  60. } catch (NoClassDefFoundError var6) {
  61. if(currentWorthTrying == null) {
  62. this.worthTrying = Boolean.FALSE;
  63. }
  64. throw new ObjenesisException(var6);
  65. }
  66. }
  67. }

到此,关于Spring AOP内部实现原理分析就结束了。

作者:FX_SKY
链接:https://www.jianshu.com/p/16a2ad9f4fbc
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

[Image 1]:

发表评论

表情:
评论列表 (有 0 条评论,282人围观)

还没有评论,来说两句吧...

相关阅读

    相关 AOP底层实现

    AOP是目前Spring框架中的核心之一,在应用中具有非常重要的作用,也是Spring其他组件的基础。它是一种面向切面编程的思想。关于AOP的基础知识,相信多数童鞋都已经了如

    相关 Spring AOP底层实现技术

    AOP概述   软件的编程语言最终的目的就是用更自然更灵活的方式模拟世界,从原始机器语言到过程语言再到面向对象的语言,我们看到编程语言在一步步用更自然、更强大的方式描述软件。