Spring AOP中如何为Bean创建代理?

简介: Spring AOP中如何为Bean创建代理?

在Spring AOP使用(踩坑)实践总结及IOC容器的依赖注入详解我们提到过,当Bean实例化过程中会触发BeanPostProcessor的动作。其中 AbstractAutoProxyCreator的postProcessAfterInitialization方法(这个方法在initializeBean方法中触发) 中我们可以看到其会尝试对Bean进行代理。

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  if (bean != null) {
    // 获取缓存key
    Object cacheKey = getCacheKey(bean.getClass(), beanName);
    // 如果earlyProxyReferences中不存在 {cacheKey,bean},执行wrapIfNecessary
    if (this.earlyProxyReferences.remove(cacheKey) != bean) {
      return wrapIfNecessary(bean, beanName, cacheKey);
    }
  }
  return bean;
}

本文我们尝试分析Spring AOP如何对bean进行包装代理的。假设我们定义了切片如下所示:

@Aspect
@Component
public class LogAspect {
    @Pointcut("execution(* com.recommend.controller.*.*(..))")
    public void logPointCut() {
    }
    @Before(value = "execution(* com.recommend.controller.*.*(..))")
    public void beforeMethod(JoinPoint point)  {
        System.out.println(" before(Joinpoint point)");
    }
    @After("logPointCut()")
    public void afterMethod(JoinPoint point)  {
        System.out.println(" afterMethod(Joinpoint point)");
    }
    @AfterReturning(pointcut = "logPointCut()",returning="result")
    public void AfterReturning(JoinPoint point,Object result)  {
        System.out.println(" AfterReturning(Joinpoint point)");
    }
    @AfterThrowing(value = "logPointCut()",throwing="exception")
    public void AfterThrowing(JoinPoint point,Exception exception)  {
        System.out.println(" AfterThrowing(Joinpoint point)");
    }
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        // 执行方法
        Object result = point.proceed();
        // 执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;
        //异步保存日志
        return result;
    }
}

接下来我们来看AbstractAutoProxyCreatorwrapIfNecessary方法。

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 如果当前bean有自定义targetSource,直接返回
  if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
    return bean;
  }
// 如果当前bean无需代理,直接返回  
  if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
    return bean;
  }
//如果当前bean是Advice、Pointcut、Advisor或者AopInfrastructureBean可以直接返回
//如果当前bean是original instance,那么也直接返回,如XXXX.ORIGINAL 命名的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);
  // DO_NOT_PROXY=null
  //如果没有specificInterceptors ,则不创建代理
  if (specificInterceptors != DO_NOT_PROXY) {
    // 保存代理标志 Map<Object, Boolean> advisedBeans
    this.advisedBeans.put(cacheKey, Boolean.TRUE);
    // 创建代理
    Object proxy = createProxy(
        bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
    // Map<Object, Class<?>> proxyTypes 保存代理类型
    this.proxyTypes.put(cacheKey, proxy.getClass());
    return proxy;
  }
  // 走到这里说明无需创建代理
  this.advisedBeans.put(cacheKey, Boolean.FALSE);
  return bean;
}

从上面方法我们可以看到,如果当前bean拥有advice,也就是我们定义的切面表达式拦截了当前bean的某个方法,那么就会尝试创建代理并在advisedBeans存储代理标志。


这里有这样关键的两步:


getAdvicesAndAdvisorsForBean获取advice

createProxy,创建代理


那什么时候不需要对bean进行代理呢?

// targetSourcedBeans包含beanName,也就是bean有custom TargetSource
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;
}

isInfrastructureClass(bean.getClass()):Advice、Pointcut、Advisor、AopInfrastructureBean或者有@Aspect注解


shouldSkip:XXX.ORIGINAL格式命名的bean或者该bean是AspectJPointcutAdvisor且aspectName==beanName


【1】getAdvicesAndAdvisorsForBean


我们先看一下获取到的Object[] specificInterceptors是个什么。如下所示,在这里其获取到是一个advisor数组,每个advisor呢主要有pointcut与advice组成。前者表示连接点,后置表示应用的增强通知。


那么为什么用specificInterceptors命名呢,而且其方法名字是getAdvicesAndAdvisorsForBean。也就是说这里不仅仅是advisor,还可能是advice。

如下所示,在AbstractAutoProxyCreator内部其是一个抽象方法并没有提供实现。

@Nullable
protected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,
    @Nullable TargetSource customTargetSource) throws BeansException;

主要的实现在子类AbstractAdvisorAutoProxyCreator中。

@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
    Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
  List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
  if (advisors.isEmpty()) {
    return DO_NOT_PROXY;
  }
  return advisors.toArray();
}

这里我们继续看findEligibleAdvisors(beanClass, beanName)方法。

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 找到所有的Advisor && this.aspectJAdvisorsBuilder.buildAspectJAdvisors()
  List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 为当前bean从候选candidateAdvisors找到可以应用的advisor
  List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
  // 扩展Advisor 如果eligibleAdvisors不为空
  //则在首位添加ExposeInvocationInterceptor.ADVISOR
  extendAdvisors(eligibleAdvisors);
  if (!eligibleAdvisors.isEmpty()) {
  // 使用AnnotationAwareOrderComparator进行排序
    eligibleAdvisors = sortAdvisors(eligibleAdvisors);
  }
  return eligibleAdvisors;
}

第一步findCandidateAdvisors方法使用找到容器中的Advisor。

// AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
@Override
protected List<Advisor> findCandidateAdvisors() {
  // Add all the Spring advisors found according to superclass rules.
  // 找到所有的Advisor
  List<Advisor> advisors = super.findCandidateAdvisors();
  // Build Advisors for all AspectJ aspects in the bean factory.
  // 这里会触发Advisor的创建 --如我们切面的通知会和poincut一起被保证为advisor
  if (this.aspectJAdvisorsBuilder != null) {
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
  }
  return advisors;
}
// super.findCandidateAdvisors(); 
//AbstractAdvisorAutoProxyCreator#findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
  Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
  return this.advisorRetrievalHelper.findAdvisorBeans();
}

如下图所示,我们自定义的logAspect也在列。


第二步,findAdvisorsThatCanApply方法从上面得到的候选Advisor中寻找到可以应用到目标Bean的advisor。

// AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply
protected List<Advisor> findAdvisorsThatCanApply(
    List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
  ProxyCreationContext.setCurrentProxiedBeanName(beanName);
  try {
    return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
  }
  finally {
    ProxyCreationContext.setCurrentProxiedBeanName(null);
  }
}


如果当前advisor是IntroductionAdvisor,那么将会得到其ClassFilter然后调用matches方法默认DefaultIntroductionAdvisor的matches方法是true。


如果是PointcutAdvisor,那么将会获取到Pointcut进而得到MethodMatcher。最终会通过MethodMatcher与目标类的所有方法进行匹配


第三步,extendAdvisors扩展advisor。这是给子类提供的一个扩展钩子,允许子类覆盖该方法并注册额外Advisor。默认实现是空,子类AspectJAwareAdvisorAutoProxyCreator重写了该方法,会尝试在首位添加ExposeInvocationInterceptor.ADVISOR。

//AspectJAwareAdvisorAutoProxyCreator#extendAdvisors
@Override
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
  AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}
// 如果advisor包含advice且candidateAdvisors没有ExposeInvocationInterceptor.ADVISOR,
// 则尝试将其加入candidateAdvisors

第四步,如果最终eligibleAdvisors 不为空,那么将使用AnnotationAwareOrderComparator进行排序(按照advisor的order值进行排序)。


单个Aspect内部排序后的结果是(从上到下):

AfterThrowing>AfterReturning>After>Around>Before


至此,我们得到了List<Advisor> advisors,转换为array返回。

【2】创建代理

也就是下面这句代码。

// AbstractAutoProxyCreator#createProxy
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, 
new SingletonTargetSource(bean));

那么接下来我们分析createProxy这个方法。

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
    @Nullable Object[] specificInterceptors, TargetSource targetSource) {
// 记录原始bean 类型,放到关联的beanDefinition的Map<String, Object> attributes中
  if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
    AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
  }
// 创建代理工厂,用来获取AopProxy
  ProxyFactory proxyFactory = new ProxyFactory();
  // 设置属性 如proxyTargetClass
  proxyFactory.copyFrom(this);
// 判断proxyTargetClass,默认为false,
//在实例化时ProxyConfig的proxyTargetClass会被设置为true
// true则意味着目标targetClass非接口时使用CGLIB对bean进行代理
  if (!proxyFactory.isProxyTargetClass()) {
    //是否代理目标类,这时采用cglib进行代理
    if (shouldProxyTargetClass(beanClass, beanName)) {
      proxyFactory.setProxyTargetClass(true);
    }
    else {
    // 这时采用JDK动态代理
      evaluateProxyInterfaces(beanClass, proxyFactory);
    }
  }
  // 从specificInterceptors获取Advisor
  Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
  //设置proxyFactory
  proxyFactory.addAdvisors(advisors);
  proxyFactory.setTargetSource(targetSource);
  //提供子类进行重写的,默认为空
  customizeProxyFactory(proxyFactory);
  // 设置冻结属性,freezeProxy默认为false
  proxyFactory.setFrozen(this.freezeProxy);
  // 默认为false AbstractAdvisorAutoProxyCreator覆盖该方法返回true
  if (advisorsPreFiltered()) {
    proxyFactory.setPreFiltered(true);
  }
  //根据代理工厂获取具体代理如ObjenesisCglibAopProxy
  //然后为bean创建代理对象
  return proxyFactory.getProxy(getProxyClassLoader());
}

根据代码来看,首先是为当前beanDefinition记录了bean的原始类型。然后实例化ProxyFactory 对其进行设置如advisors、targetSource、Frozen及PreFiltered。之后使用代理工厂获取具体AopProxy如ObjenesisCglibAopProxy或者JdkDynamicAopProxy。根据具体的AopProxy对目标Bean进行代理包装。


那么这里我们着重分析两块:


  • buildAdvisors ,解析得到Advisor数组
  • proxyFactory.getProxy(getProxyClassLoader());,创建代理对象

① buildAdvisors

Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
    // Handle prototypes correctly...
    Advisor[] commonInterceptors = resolveInterceptorNames();
// 如果有公共的拦截器且applyCommonInterceptorsFirst为true,
// 则放在allInterceptors第一个位置
    List<Object> allInterceptors = new ArrayList<>();
    if (specificInterceptors != null) {
      allInterceptors.addAll(Arrays.asList(specificInterceptors));
      if (commonInterceptors.length > 0) {
        if (this.applyCommonInterceptorsFirst) {
          allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
        }
        else {
        // 否则直接addAll,不指定位置
          allInterceptors.addAll(Arrays.asList(commonInterceptors));
        }
      }
    }
    if (logger.isTraceEnabled()) {
      int nrOfCommonInterceptors = commonInterceptors.length;
      int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
      logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
          " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
    }
// 对每一个allInterceptors中的对象进行包装得到Advisor
    Advisor[] advisors = new Advisor[allInterceptors.size()];
    for (int i = 0; i < allInterceptors.size(); i++) {
      advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
    }
    return advisors;
  }


如上代码所示,先尝试得到公共的拦截器,如果有则放到allInterceptors中。然后对对每一个allInterceptors中的对象进行包装得到Advisor。


这里我们解释一下拦截器。在前面源码我们可以看到诸多xxxxInterceptor命名的变量,这个其实和我们通常理解的Interceptor接口不一样,这里是业务含义指拦截方法处理前后进行增强通知,具体的bean可能是InstantiationModelAwarePointcutAdvisorImpl或者ExposeInvocationInterceptor.ADVISOR。


我们继续往下看DefaultAdvisorAdapterRegistry是如何对adviceObject进行包装返回Advisor的。

public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
  if (adviceObject instanceof Advisor) {
    return (Advisor) adviceObject;
  }
  if (!(adviceObject instanceof Advice)) {
    throw new UnknownAdviceTypeException(adviceObject);
  }
  Advice advice = (Advice) adviceObject;
  if (advice instanceof MethodInterceptor) {
    // So well-known it doesn't even need an adapter.
    return new DefaultPointcutAdvisor(advice);
  }
  for (AdvisorAdapter adapter : this.adapters) {
    // Check that it is supported.
    if (adapter.supportsAdvice(advice)) {
      return new DefaultPointcutAdvisor(advice);
    }
  }
  throw new UnknownAdviceTypeException(advice);
}

方法解释如下:


① 如果是Advisor,直接返回;

② 如果不是Advice,抛出异常UnknownAdviceTypeException

③ 如果是MethodInterceptor,返回DefaultPointcutAdvisor;

④ 尝试返回DefaultPointcutAdvisor

⑤ 抛出异常DefaultPointcutAdvisor


默认在构建DefaultAdvisorAdapterRegistry实例时注册了三个适配器。

public DefaultAdvisorAdapterRegistry() {
  registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
  registerAdvisorAdapter(new AfterReturningAdviceAdapter());
  registerAdvisorAdapter(new ThrowsAdviceAdapter());
}

至此我们解析得到了Advisor,就可以交给ProxyFactory创建代理了。

② proxyFactory.getProxy

如下所示ProxyFactory的getProxy方法。

// ProxyFactory#getProxy(java.lang.ClassLoader)
public Object getProxy(@Nullable ClassLoader classLoader) {
  return createAopProxy().getProxy(classLoader);
}


这里最终会走两个分支:JdkDynamicAopProxy和CglibAopProxy。我们先看一下createAopProxy()

ProxyCreatorSupport的createAopProxy方法。

protected final synchronized AopProxy createAopProxy() {
  //如果为激活,进行激活
  if (!this.active) {
    activate();
  }
  // 这里默认是DefaultAopProxyFactory
  return getAopProxyFactory().createAopProxy(this);
}
/**
 * Activate this proxy configuration.
 */
private void activate() {
  this.active = true; // 设置为true
  // 遍历监听,默认情况下不存在AdvisedSupportListener 
  for (AdvisedSupportListener listener : this.listeners) {
    listener.activated(this);
  }
}


DefaultAopProxyFactory的createAopProxy得到具体的AopProxy

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 如果optimize为true或者proxyTargetClass为true或者 是否有非SpringProxy接口超类
  if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
    // 这里其实是从targetSource中获取targetClass
    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.");
    }
    // 如果targetClass是接口或者其是一个Proxy代理类
    if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
      return new JdkDynamicAopProxy(config);
    }
    return new ObjenesisCglibAopProxy(config);
  }
  else {
    return new JdkDynamicAopProxy(config);
  }
}


这里会根据targetClass是类 or 接口返回ObjenesisCglibAopProxy或者JdkDynamicAopProxy。


那么接下来就该执行具体的getProxy(classLoader)方法了。


在代理对象的生成过程中,首先要从AdvisedSupport对象中取得配置的目标对象,这个目标对象是实现AOP功能所必需的,如果不存在将直接抛出异常,提醒AOP应用需要提供正确的目标对象的配置。在对目标对象的配置的检查完成以后,需要根据配置的情况来决定用什么方式来创建代理对象。一般而言,默认的方式是使用jdk来产生代理对象。但是遇到的配置的目标对象不是接口类的实现,会使用CGLIB来产生代理对象。


③ JdkDynamicAopProxy创建代理


如下所示,在JdkDynamicAopProxy中,使用了jdk 的Proxy类来生成代理对象,在生成Proxy对象之前,首先需要从advised对象中取得代理对象的代理接口配置,然后调用Proxy的newProxyInstance方法,最终得到对应的Proxy代理对象。


在生成代理对象时,需要指明三个参数,一个是类加载器,一个是代理接口,另外一个就是Proxy回调方法所在的对象,这个对象需要实现InvocationHandler接口。


这个InvocationHandler接口定义了invoke方法,提供了代理对象的回调入口。对于JdkDynamicAopProxy,它本身实现了InvocationHandler接口和invoke方法,这个invoke方法是Proxy代理对象的回调方法,所以可以使用this来把JdkDynamicAopProxy指派给Proxy对象(也就是说JdkDynamicAopProxy对象本身)。在Proxy代理的接口方法被调用时,会触发invoke方法的回调,这个回调方法完成了AOP编织实现的封装。

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
  if (logger.isTraceEnabled()) {
    logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
  }
  // 获取代理的接口类型数组
  Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
  // 判断接口是否有equals 或者 hashCode方法
  findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
  // 生成代理
  return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

④ CglibAopProxy创建代理


在CglibAopProxy创建代理的过程会为切面拦截的目标类的目标方法创建拦截器链也就是List<?> chain其实就是MethodInterceptor[]。然后放到AdvisedSupport的Map<MethodCacheKey, List<Object>> methodCache中。这样在触发目标方法时候会按照这个拦截器链进行增强。

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
  if (logger.isTraceEnabled()) {
    logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
  }
  try {
  // 从advised中取得在IOC容器中配置的target对象
    Class<?> rootClass = this.advised.getTargetClass();
    Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
    Class<?> proxySuperClass = rootClass;
    // CGLIB_CLASS_SEPARATOR = "$$";
    if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
      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...
    // 创建并配置CGLIB的Enhancer,这个Enhancer对象是CGLIB的主要操作类
    Enhancer enhancer = createEnhancer();
    if (classLoader != null) {
      enhancer.setClassLoader(classLoader);
      if (classLoader instanceof SmartClassLoader &&
          ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
        enhancer.setUseCache(false);
      }
    }
    // 设置Enhancer对象,包括设置代理接口、回调方法
    enhancer.setSuperclass(proxySuperClass);
//设置接口,如SpringProxy  Advised    
    enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
    // SpringNamingPolicy
    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
  // 这里是核心,设置回调拦截器,如DynamicAdvisedInterceptor
    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);
    // 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);
  }
}

在ObjenesisCglibAopProxy中实现了代理实例的创建与回调的设置。

@Override
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
  Class<?> proxyClass = enhancer.createClass();
  Object proxyInstance = null;
  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);
    }
  }
  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;
}

在这个生成代理对象的过程中,需要注意的是对Enhancer对象callback回调的设置,正是这些回调封装了Spring AOP的实现,就像前面介绍的jdk的proxy对象的invoke回调方法一样。在Enhancer的callback回调设置汇总,实际上是通过设置DynamicAdvisedInterceptor拦截器来完成AOP功能的。


作为AOP实现的一部分,对target目标对象的方法调用会首先被AOPProxy代理对象拦截,对于不同的AopProxy代理对象的生成方式,会使用不同的拦截回调入口。例如对于jdk的代理对象,使用的是InvocationHandler的invoke回调入口。对于CGLIB的代理对象,使用的是设置好的callback回调。在这些callback回调中,对于AOP实现是通过DynamicAdvisedInterceptor来完成的,而其回调入口是intercept方法。

【3】AOP两种代理


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


① JDK动态接口代理


JDK 动态代理主要涉及到 java.lang.reflect 包中的两个类:Proxy 和 InvocationHandler。


InvocationHandler是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编制在一起。Proxy 利用 InvocationHandler 动态创建一个符合某一接口的实例,生成目标类的代理对象。


JDK动态代理只能为接口创建动态代理实例,而不能对类创建动态代理。需要获得被目标类的 接口信息(应用Java的反射技术),生成一个实现了代理接口的动态代理类(字节码),再通过 反射机制获得动态代理类的构造函数,利用构造函数生成动态代理类的实例对象,在调用具体方法前调用invokeHandler方法来处理。

② CGLib 动态代理


CGLib 全称为 Code Generation Library,是一个强大的高性能,高质量的代码生成类库,可以在运行期扩展 Java 类与实现 Java 接口,CGLib 封装了 asm,可以在运行期动态生成新的 class。CGLib动态代理需要依赖asm包,把被代理对象类的class文件加载进来,修改其字节码生成 子类


JDK 创建代理有一个限制,就是只能为接口创建代理实例,而对于没有通过接口定义业务方法的类,则可以通过 CGLib 创建动态代理。

目录
相关文章
|
5月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
610 0
|
9月前
|
监控 安全 Java
Spring AOP实现原理
本内容主要介绍了Spring AOP的核心概念、实现机制及代理生成流程。涵盖切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)等关键概念,解析了JDK动态代理与CGLIB代理的原理及对比,并深入探讨了通知执行链路和责任链模式的应用。同时,详细分析了AspectJ注解驱动的AOP解析过程,包括切面识别、切点表达式匹配及通知适配为Advice的机制,帮助理解Spring AOP的工作原理与实现细节。
1362 13
|
4月前
|
XML Java 数据格式
《深入理解Spring》:AOP面向切面编程深度解析
Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
|
6月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
6月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
XML Java 测试技术
Spring AOP—通知类型 和 切入点表达式 万字详解(通俗易懂)
Spring 第五节 AOP——切入点表达式 万字详解!
908 25
|
XML 安全 Java
Spring AOP—深入动态代理 万字详解(通俗易懂)
Spring 第四节 AOP——动态代理 万字详解!
510 24
|
11月前
|
Java API 微服务
微服务——SpringBoot使用归纳——Spring Boot中的切面AOP处理——Spring Boot 中的 AOP 处理
本文详细讲解了Spring Boot中的AOP(面向切面编程)处理方法。首先介绍如何引入AOP依赖,通过添加`spring-boot-starter-aop`实现。接着阐述了如何定义和实现AOP切面,包括常用注解如`@Aspect`、`@Pointcut`、`@Before`、`@After`、`@AfterReturning`和`@AfterThrowing`的使用场景与示例代码。通过这些注解,可以分别在方法执行前、后、返回时或抛出异常时插入自定义逻辑,从而实现功能增强或日志记录等操作。最后总结了AOP在实际项目中的重要作用,并提供了课程源码下载链接供进一步学习。
1495 0