首页 > 其他分享 >Spring代理机制

Spring代理机制

时间:2023-08-05 14:44:52浏览次数:31  
标签:return 创建 Spring 代理 bean Advisor 机制 public

前言

代理的使用在Spring中是用的非常的多,如AOP、声明式事务(@Transactional)、异步任务(@Async)、缓存(@Cacheable,@CachePut,@CacheEvict)这些使用注解来增强逻辑的功能都是通过代理来实现的。那么Spring是何时来帮我们创建代理,怎样创建代理呢?

概述

众所周知,Spring创建代理时,底层有两种方式可选

  • JDK动态代理
  • CGLIB代理
    默认情况下,如果目标类有实现接口,则使用JDK动态代理技术来创建代理类,否则使用CGLIB技术来创建。
    @EnableTransactionManagement开启事务注解类来举例,其他如@EnableCaching@EnableAsync等开启缓存注解(@Cacheable),开启异步任务注解(@Async)是一样的。
public @interface EnableTransactionManagement {

    boolean proxyTargetClass() default false;

    AdviceMode mode() default AdviceMode.PROXY;

}
  • proxyTargetClass属性用于控制使用哪种代理技术来创建代理类,默认为false,也就是使用JDK动态代理(目标没有实现接口,则转为CGLIB技术)。若指定为true,则直接使用CGLIB技术。
  • mode属性是用于指定增强逻辑是采用代理(PROXY)还是ASPECTJ,若指定为ASPECTJ,则proxyTargetClass属性无效。
    注: ASPECTJ是使用字节码织入实现,会修改目标类的字节码文件,直接将增强逻辑插入到对应字节码文件中,需要使用特定的ajc编译器编译。

开胃菜,自定义注解模拟添加缓存

相信如果使用AOP的一些注解来实现这个逻辑,基本上很多人都会写。但是如果不使用AOP那些注解呢,有人可能会想到BeanPostProcessor,没错就是它,但是我们只写增强逻辑,创建代理还是交给Spring自己来实现,创建代理的类其实就是一个BeanPostProcessor,Spring已经为我们写好了。

我们只需要编写一个Advisor放入到容器中即可,Advisor包含了PointCut、Advise。是不是发现和AOP很像,只不过一个是接口,一个注解,想象就对了,毕竟AOP也是通过这套机制来实现的。

  • PointCut,切点,用于判断一个类是否需要使用本Advisor来增强。
  • Advice,用于封装增强逻辑。
    PointCut和Advice就组成了Advisor,AOP中的@Aspect切面其实就是会被解释成一个Advisor。

第一步,编写注解,用于标识哪个方法需要被增强

@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.METHOD)  
@Inherited  
@Documented  
public @interface MyCacheable {  
  
}

第二步,编写Advisor

/**
 * 实现很简单,只要指定PointCut, Advice即可
 * 在不开启AOP时,Spring默认情况下只认识角色为BeanDefinition.ROLE_INFRASTRUCTURE的Advisor Bean
 */
@Slf4j
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Component
public class MyCacheAdvisor extends AbstractBeanFactoryPointcutAdvisor {

    private final Pointcut pointcut;

    public MyCacheAdvisor() {
        /*
         * 定义切点
         * 第一个参数为null,表示所有的类都符合
         * 第二参数为@MyCacheable,表示只有被@MyCacheable注解的方法符合条件
         * 第三个参数为true,表示会检查父类或者接口上的方法有没有指定的注解
         * 比如目标实现类方法没有加@MyCacheable注解,但是接口上的该方法有@MyCacheable注解,也是符合条件的。
         */
        this.pointcut = new AnnotationMatchingPointcut(null, MyCacheable.class, true);
        this.setAdvice(new MyCacheAdvice());
    }

    @NonNull
    @Override
    public Pointcut getPointcut() {
        return pointcut;
    }

    /**
     * MethodInterceptor继承了Advice接口
     */
    static class MyCacheAdvice implements MethodInterceptor {

        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            // 获取目标对象
            log.info("obj: {}", invocation.getThis());
            // 获取方法参数
            log.info("args: {}", Arrays.toString(invocation.getArguments()));
            // 执行目标方法
            Object result = invocation.proceed();
            // 模拟添加缓存
            log.info("put cache: {}", result);
            return result;
        }
    }

}

第三步,编写样例

@Component  
public class MyCacheExample {  
  
    @MyCacheable  
    public String getById(Integer id) {  
        return "str-" + id;  
    }  
}

结果

obj: com.wangtao.springboottest.mycache.MyCacheExample@3af58f76
args: [1]
put cache: str-1
str-1

原理解析

由于ASPECTJ增强模式用的很少,且需要特定的编译器(ajc)来编译,因此只分析PROXY模式。

先简单熟悉下一些关键的类或接口。

PointCut接口

简单来说就是用于判断目标类是否需要创建代理

public interface Pointcut {  
  
    /**
     * 用于过滤类
     */
    ClassFilter getClassFilter();  
      
    /**
     * 类满足了再看有没有匹配的方法
     */
    MethodMatcher getMethodMatcher();  
      
    /**
     * 一个常量,表示所有情况都满足(排除掉那些失效场景,比如不是public方法,被final修饰(cglib))
     */  
    Pointcut TRUE = TruePointcut.INSTANCE;  
  
}

Advice接口

用于表示增强逻辑,有很多子接口,比如MethodInterceptorBeforeAdviceAfterAdvice等。

/**
 * 顶层标记接口
 */
public interface Advice {  
  
}

/**
 * 比较灵活,目标方法由自己调用
 * Interceptor接口继承了Advice接口
 */
@FunctionalInterface  
public interface MethodInterceptor extends Interceptor {  

    /**
     * 增强逻辑
     * 可以拿到目标方法,目标对象,方法参数
     */
    Object invoke(MethodInvocation invocation) throws Throwable;  
}

/**
 * 前置通知,在目标方法执行之前执行
 */
public interface MethodBeforeAdvice extends BeforeAdvice {  
  
    void before(Method method, Object[] args, @Nullable Object target) throws Throwable;  
  
}

/**
 * 后置通知,子类实现又细分为目标方法执行成功后执行,还是执行发生异常时执行
 */
public interface AfterAdvice extends Advice {  
  
}

Advisor接口

可以简单理解为PointCutAdvice的组合,当目标方法满足条件后,使用其中对应的Advice来增强。

public interface Advisor {

    /**
     * 空实现
     */
    Advice EMPTY_ADVICE = new Advice() {};

    /**
     * 获取Advice
     */
    Advice getAdvice();

   
    boolean isPerInstance();

}

public interface PointcutAdvisor extends Advisor {

    /**
     * 增加获取PointCut方法
     */
    Pointcut getPointcut();

}

AbstractAutoProxyCreator基类

该类是一个BeanPostProcessor,也就是为Spring容器中的Bean自动创建代理的入口。下面是它的一个继承体系图。

目前Spring用到的实现类主要是下面这两个。

  • InfrastructureAdvisorAutoProxyCreator
  • AnnotationAwareAspectJAutoProxyCreator

其中AnnotationAwareAspectJAutoProxyCreator几乎拥有InfrastructureAdvisorAutoProxyCreator所有的功能,除此之外,还扩展了AspectJ的一些注解,如@Aspect@PointCut@Before@After@Around等,会对这些注解注解的类进行代理增强。

其中@EnableAspectJAutoProxy就是会自动注册AnnotationAwareAspectJAutoProxyCreator到容器中,用于支持Spring AOP注解切面编程。而@EnableTransactionManagement@EnableCaching会自动注册InfrastructureAdvisorAutoProxyCreator用于增强方法逻辑。@EnableAsync则干脆自己注册了一个别的BeanPostProcessor来创建代理,因为Spring可能并不想异步任务bean也能循环依赖。

AnnotationAwareAspectJAutoProxyCreatorInfrastructureAdvisorAutoProxyCreator自动注册时在容器中只能存在一个,并且AnnotationAwareAspectJAutoProxyCreator优先级更高,因为它的功能更全。

AbstractAutoProxyCreator封装了创建代理的逻辑,寻找Advisor的逻辑则交给子类来实现,比如从容器获取所有的Advisor,然后利用Advisor中的PointCut来和当前bean去匹配,挑出所有的符合的Advisor后,进行代理创建。

ProxyFactory类

该类就是用于创建代理,AbstractAutoProxyCreator内部就是使用它来创建代理的。由于创建代理分为JDK动态代理和CGLIB,于是便又有了AopProxy,它有的子类实现JdkDynamicAopProxyObjenesisCglibAopProxy

public class ProxyFactory extends ProxyCreatorSupport {

    /**
     * 创建代理,根据proxyTargetClass来选择使用JDK还是CGLIB
     */
    public Object getProxy() {
        return createAopProxy().getProxy();
    }
}
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            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.");
            }
            /*
             * 如果目标类是一个接口或者是一个JDK动态代理生成的类
             * 即便proxyTargetClass=true,依然使用JDK动态代理
             */
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }

}

源码流程分析

通过@EnableAspectJAutoProxy@EnableTransactionManagement@EnableAsync 这3个注解来分析,为什么是这3个,前面两个都是自动创建代理(自动创建的代理类的BeanPostProcessor不同),后面一个是手动创建,自己注册了一个别的BeanPostProcessor来创建代理,非 AbstractAutoProxyCreator子类。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

    /**
     * 全局配置,是使用JDK动态代理还是CGLIB
     */
    boolean proxyTargetClass() default false;

    
    /**
     * 是否暴露代理对象到ThreadLocal中,可以通过AopContext.currentProxy()方法拿到代理对象
     * 比如一个类中有两个方法a, b。其中a方法调用b方法,此时调用b方法的对象是目标对象而不是代理对象,导致
     * b方法没有增强逻辑。此时在a方法中,则可以通过AopContext.currentProxy()拿到代理对象再去调用b方法
     */
    boolean exposeProxy() default false;
}
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * 就是注册了AnnotationAwareAspectJAutoProxyCreator类
     */
    @Override
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

        AnnotationAttributes enableAspectJAutoProxy =
                AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
            // 设置proxyTargetClasss属性
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            // 设置exposeProxy属性
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }

}

再看@EnableTransactionManagement

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

    /**
     * 不再赘述
     */
    boolean proxyTargetClass() default false;

    
    /**
     * 增强模式, PROXY还是ASPECTJ
     */    
    AdviceMode mode() default AdviceMode.PROXY;

}
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

    
    /**
     * 1. 注册了AutoProxyRegistrar, 而AutoProxyRegistrar又注册了InfrastructureAdvisorAutoProxyCreator
     * 2. 注册了ProxyTransactionManagementConfiguration,该类主要注册了一个Advisor
     *    通过前面铺垫我们知道InfrastructureAdvisorAutoProxyCreator是从容器中拿Advisor
     *    创建代理,增强方法逻辑的
     */
    @Override
    protected String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) {
            case PROXY:
                return new String[] {AutoProxyRegistrar.class.getName(),
                        ProxyTransactionManagementConfiguration.class.getName()};
            case ASPECTJ:
                return new String[] {determineTransactionAspectClass()};
            default:
                return null;
        }
    }

}

如果多个注册同时存在,只会保留AnnotationAwareAspectJAutoProxyCreator,并且proxyTargetClassexposeProxy的值原先为false,后面为true才会发生属性值的覆盖。

具体看

public abstract class AopConfigUtils {

    @Nullable
    public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
        return registerAutoProxyCreatorIfNecessary(registry, null);
    }

    @Nullable
    public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
        return registerAspectJAutoProxyCreatorIfNecessary(registry, null);
    }

    /**
     * 覆盖proxyTargetClass属性
     */
    public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
        if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
            BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
            definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
        }
    }

    
    /**
     * 覆盖exposeProxy属性
     */
    public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
        if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
            BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
            definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
        }
    }

    @Nullable
    private static BeanDefinition registerOrEscalateApcAsRequired(
            Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

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

        // 如果bean已经存在
        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;
    }

}

最后是@EnableAsync

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {
    
    /**
     * 指定要拦截的注解, 默认是@Async
     */
    Class<? extends Annotation> annotation() default Annotation.class;

   
    boolean proxyTargetClass() default false;

    
    AdviceMode mode() default AdviceMode.PROXY;

}


public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {

    private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
            "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";


    /**
     * 注册了ProxyAsyncConfiguration, 而它又注册了AsyncAnnotationBeanPostProcessor
     */
    @Override
    @Nullable
    public String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) {
            case PROXY:
                return new String[] {ProxyAsyncConfiguration.class.getName()};
            case ASPECTJ:
                return new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};
            default:
                return null;
        }
    }

}

通过这3个注解注册的东西,可以总结下规律。

  • @EnableAspectJAutoProxy仅仅注册了AnnotationAwareAspectJAutoProxyCreator,并没有注册Advisor,很好理解,因为Spring AOP需要我们自己写切面,实现增强逻辑。@Aspect其实就是相当于Advisor,是由用户注册到容器的。
  • @EnableTransactionManagement不仅注册了InfrastructureAdvisorAutoProxyCreator,还注册了自己的Advisor
  • @EnableAsync仅仅注册了AsyncAnnotationBeanPostProcessor,用于创建自己的代理,当然了这个类内部自己设置了自己所需要的Advisor,而没有把Advisor注册到容器中,因为如果把Advisor注册到容器中,则会重复代理,不管是AnnotationAwareAspectJAutoProxyCreator还是InfrastructureAdvisorAutoProxyCreator都会从容器中获取Advisor这几个BeanPostProcessor创建代理的底层是一样的,都是通过ProxyFactory实现。
  • @EnableAsync为啥选择使用AsyncAnnotationBeanPostProcessor而不是AbstractAutoProxyCreator的子类,我想是Spring团队不希望异步任务bean发生循环依赖吧。AsyncAnnotationBeanPostProcessor没有实现SmartInstantiationAwareBeanPostProcessor接口。

因此如果想要Spring为我们创建代理,最简单的方式就是编写一个Advisor注册到容器即可。

最后来分析下最重要的AbstractAutoProxyCreator,毫无疑问从BeanPostProcessor的钩子方法入手。

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        /*
         * 如果当前bean发生了循环依赖,即getEarlyBeanReference方法会调用
         * 直接返回,不再重复创建代理。getEarlyBeanReference方法内部也
         * 调用了wrapIfNecessary方法
         *
         * 注: 这里的bean还是目标对象,不是代理对象,发生循环依赖,getBean方法
         * 会直接从二级缓存拿到代理对象,然后放到容器中。 
         * 可参见AbstractAutowireCapableBeanFactory.doCreateBean方法
         */
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}
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;
    }

    // 寻找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) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }

    // 每次的创建一个新的实例
    ProxyFactory proxyFactory = new ProxyFactory();
    // 复制全局的属性, 如proxyTargetClass、exposeProxy
    proxyFactory.copyFrom(this);

    // 如果是JDK动态代理,则检查有没有实现接口,若没有,强制实现CGLIB
    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            // 添加接口到ProxyFactory中
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    // 添加advisor
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }
    // 返回代理对象
    return proxyFactory.getProxy(getProxyClassLoader());
}

子类AbstractAdvisorAutoProxyCreator.java

@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
        Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
    // 寻找满足条件的advisor,因为advisor里就有advice
    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
        return DO_NOT_PROXY;
    }
    return advisors.toArray();
}

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    
    // 候选者, 仅仅只是第一步筛选(从容器中获取advisor)
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    /*
     * 将这些候选者与当前创建的bean进行匹配,挑选出符合条件的advisor
     * 这里会把Advisor分类,有PointCut,则使用PointCut筛选
     */
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

AnnotationAwareAspectJAutoProxyCreatorInfrastructureAdvisorAutoProxyCreator都是AbstractAdvisorAutoProxyCreator的子类,仅仅扩展了挑选Advisor的条件罢了。

  • InfrastructureAdvisorAutoProxyCreator,只需要容器中role为BeanDefinition.ROLE_INFRASTRUCTUREAdvisor
  • AnnotationAwareAspectJAutoProxyCreator,除了容器中的Advisor,还会把@Aspect注解的bean上面的关于AspectJ的注解信息解析成Advisor。不过它不要求Advisor的role为BeanDefinition.ROLE_INFRASTRUCTURE

总结

  • 如果想要Spring为我们创建代理,最简单的方式就是编写一个Advisor注册到容器即可。
  • Spring自动创建代理的基类为AbstractAutoProxyCreator,它下面有两个实现,分别为InfrastructureAdvisorAutoProxyCreatorAnnotationAwareAspectJAutoProxyCreator。后者拥有前者的功能,如果应用中有开启AOP,即使用了@EnableAspectJAutoProxy,Spring Boot中如果引入了spring-boot-starter-aop,则自动开启AOP,那么自动创建代理的类就是AnnotationAwareAspectJAutoProxyCreator,它支持把@Aspect注解解析成Advisor
  • 何为自动创建代理,简单理解成自动从容器中寻找AdviceAdvisor中就有Advice),然后帮应用创建代理对象。即AbstractAutoProxyCreator的子类实现。
  • Spring中也有不用AbstractAutoProxyCreator去创建代理的功能,而是使用别的BeanPostProcessor去创建代理类,比如@EnableAsync。如果使用这种方式,就不要把Advisor注册到容器里,否则会和AbstractAutoProxyCreator冲突,重复创建代理。
  • Spring创建的代理对象都会实现Advised接口,从这个接口我们可以获取到目标对象。getTargetSource方法,或者直接通过工具类AopProxyUtils.getSingletonTarget(proxy)获取。

一些注意的点

  • Spring中的AOP实现仅仅只是使用了AspectJ的一些注解,如@Aspect@PointCut@Before@After@Around等,并没有使用AspectJ的字节码织入,而是采用动态代理(JDK、CGLIB)来增强。
  • 只有通过AbstractAutoProxyCreator,严谨的说是SmartInstantiationAwareBeanPostProcessor接口的实现增强的bean才支持循环依赖,因为Spring在解决循环依赖时使用了该接口的getEarlyBeanReference方法获取代理类。而AbstractAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor。这里举个例子,就是EnableAsync注解支持的异步任务增强bean就不支持循环依赖,容器启动时会发生错误,因为异步任务不是通过AbstractAutoProxyCreator增强的,而是另外的BeanPostProcessor

标签:return,创建,Spring,代理,bean,Advisor,机制,public
From: https://www.cnblogs.com/wt20/p/17607934.html

相关文章

  • 6、Spring之基于xml的自动装配
    6.1、场景模拟6.1.1、创建UserDao接口及实现类packageorg.rain.spring.dao;/***@authorliaojy*@date2023/8/5-11:05*/publicinterfaceUserDao{voidsaveUser();}packageorg.rain.spring.dao.impl;importorg.rain.spring.dao.UserDao;/**......
  • Spring Cloud 笔记
    单体应用存在的问题随着业务的发展,开发变得越来越复杂。修改、新增某个功能,需要对整个系统进行测试、重新部署。一个模块出现问题,很可能导致整个系统崩溃。多个开发团队同时对数据进行管理,容易产生安全漏洞。各个模块使用同一种技术进行开发,各个模块很难根据实际情况选择更......
  • 【Spring Boot 丨类型安全配置属性 】
    本篇来讲一讲外部化配置类型安全属性(类型安全配置属性)类型安全配置属性  使用@Value("${property}")注释来注入配置属性有时可能很麻烦,尤其是处理多个属性或您的数据本质上是层次结构的情况下。SpringBoot提供了另一种使用属性的方法,让强类型bean管理和验证应用程......
  • 操作系统运行机制
    操作系统通常分批处理环境、交互式环境、实时环境系统调用传递参数方法寄存器堆栈指令自带用户进程在实现系统调用的时候,通过变量传递是不能用于传递参数的 系统调用:调用程序在用户态,被调程序在核心态 处理器中对用户可见的寄存器,通常是对用户程序可用的是:地址寄存器、数据寄存器......
  • Springboot 3.x 集成Knife4j [踩坑日记]
    之前项目用的是SpringBoot2.x新项目用了SpringBoot3.x版本,引入Knife4j报错java.lang.TypeNotPresentException:Typejavax.servlet.http.HttpServletRequestnotpresent,以为是servlet的原因,更新了Servlet的版本,依旧报错,几番周折找到找到了在SpringBoot3中集成Knife......
  • C#中CLR核心机制解析:垃圾回收与标准Dispose模式
    一、CLR核心机制1.1-创建对象的流程分配内存把对象传入到构造函数构造函数使用当前实例返回1.2-什么是堆/栈?堆-Heap:托管堆;一个程序运行时,该进程存放引用类型变量的一块内存,他是全局唯一的。栈-Stack:先进后出数据结构,线程栈;每一个线程存放变量和值类型的内存,随着线程......
  • Spring Boot 数据库连接池性能优化
    当涉及到SpringBoot中的性能优化时,连接池是一个非常重要的话题。连接池在数据库访问和其他外部资源访问中扮演着关键角色,可以显著提升应用程序的性能和资源利用率。在本文中,我们将深入探讨如何在SpringBoot应用中优化数据库连接池的配置,从而提升应用性能。数据库连接池是管理......
  • Spring Boot 微服务架构中的服务发现和注册
    当涉及到SpringBoot中的微服务架构时,服务发现和注册是一个至关重要的话题。在微服务架构中,各个服务需要相互通信,而服务发现和注册机制则允许服务动态地发现和定位其他服务,从而实现更好的弹性和可扩展性。在本文中,我们将深入探讨如何在SpringBoot中实现服务发现和注册,以及如何......
  • Spring Boot 中的 AOP 实践
    在SpringBoot中使用AOP(面向切面编程)可以帮助您在应用程序中更优雅地处理横切关注点,如日志、事务管理和安全性。本文将深入探讨如何在SpringBoot中使用AOP,以及如何创建自定义切面来实现特定功能。1.什么是AOP?AOP是一种编程范式,它允许您将横切关注点(如日志、安全性、事务......
  • Spring Boot 中的缓存优化
    在SpringBoot中使用缓存可以显著提升应用程序的性能和响应时间。通过合理地配置缓存,可以减少对数据库或其他外部资源的频繁访问,从而提升系统的吞吐量和性能。本文将深入探讨如何在SpringBoot中使用缓存,以及如何优化缓存配置以获得最佳性能。1.为什么使用缓存?使用缓存可以将......