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 创建动态代理。

目录
相关文章
|
1月前
|
XML 安全 Java
|
8天前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
8天前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
14天前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
52 6
|
16天前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
80 3
|
30天前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
34 1
|
2月前
|
监控 安全 Java
什么是AOP?如何与Spring Boot一起使用?
什么是AOP?如何与Spring Boot一起使用?
69 5
|
4月前
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
AOP(面向切面编程)能够帮助我们在不修改现有代码的前提下,为应用程序添加新的功能或行为。Micronaut框架中的AOP模块通过动态代理机制实现了这一目标。AOP将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,提高模块化程度。在Micronaut中,带有特定注解的类会在启动时生成代理对象,在运行时拦截方法调用并执行额外逻辑。例如,可以通过创建切面类并在目标类上添加注解来记录方法调用信息,从而在不侵入原有代码的情况下增强应用功能,提高代码的可维护性和可扩展性。
84 1
|
2月前
|
安全 Java 编译器
什么是AOP面向切面编程?怎么简单理解?
本文介绍了面向切面编程(AOP)的基本概念和原理,解释了如何通过分离横切关注点(如日志、事务管理等)来增强代码的模块化和可维护性。AOP的核心概念包括切面、连接点、切入点、通知和织入。文章还提供了一个使用Spring AOP的简单示例,展示了如何定义和应用切面。
185 1
什么是AOP面向切面编程?怎么简单理解?
|
2月前
|
XML Java 开发者
论面向方面的编程技术及其应用(AOP)
【11月更文挑战第2天】随着软件系统的规模和复杂度不断增加,传统的面向过程编程和面向对象编程(OOP)在应对横切关注点(如日志记录、事务管理、安全性检查等)时显得力不从心。面向方面的编程(Aspect-Oriented Programming,简称AOP)作为一种新的编程范式,通过将横切关注点与业务逻辑分离,提高了代码的可维护性、可重用性和可读性。本文首先概述了AOP的基本概念和技术原理,然后结合一个实际项目,详细阐述了在项目实践中使用AOP技术开发的具体步骤,最后分析了使用AOP的原因、开发过程中存在的问题及所使用的技术带来的实际应用效果。
72 5