美文网首页
Spring AOP 自动创建代理

Spring AOP 自动创建代理

作者: Tinyspot | 来源:发表于2023-12-19 11:30 被阅读0次

    1. 代理创建器

    • 自动创建代理对象,将一个切面织入到多个目标对象中

    1.1 三种自动代理创建器

    • 基于 Bean 配置名规则的自动代理器 (BeanNameAutoProxyCreator)
    • 基于 Advisor 匹配机制的自动代理器 (DefaultAdvisorAutoProxyCreator)
    • 基于 Bean 中 AspectJ 注解标签的自动代理器 (AbstractAdvisorAutoProxyCreator)

    上述3类自动代理器都是基于 BeanPostProcessor 接口的

    2. BeanNameAutoProxyCreator

    • beanNames属性指定一组需要自动代理的 Bean 名称
    • interceptorNames属性指定一个或多个增强 Bean 的名称

    2.1 自定义拦截器链

    import org.aopalliance.aop.Advice;
    import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class BusinessInterceptorConfig {
    
        @Bean
        public Advice sessionInterceptor() {
            return new SessionInterceptor();
        }
    
        @Bean
        public Advice loginInterceptor() {
            return new LoginInterceptor();
        }
    
        @Bean
        public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
            BeanNameAutoProxyCreator creator = new BeanNameAutoProxyCreator();
            // creator.setBeanNames("greetServiceImpl", "greetService");
            creator.setBeanNames("*Impl");
            // 设置拦截链,有顺序
            creator.setInterceptorNames("sessionInterceptor", "loginInterceptor");
            // creator.setProxyTargetClass(true);
            return creator;
        }
    }
    
    @Slf4j
    public class SessionInterceptor implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            log.info(this.getClass().getSimpleName() + "; " + invocation.getMethod().getName());
            return invocation.proceed();
        }
    }
    
    @Slf4j
    public class LoginInterceptor implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            log.info(this.getClass().getSimpleName() + "; " + invocation.getMethod().getName());
            return invocation.proceed();
        }
    }
    

    2.2 自定义拦截器链2

    @Configuration
    public class BusinessInterceptorConfig {
    
        @Bean
        public Advice loginInterceptor() {
            return new LoginInterceptor();
        }
    
        /**
         * @Qualifier 作用:当有多个相同类型的Bean时,可指定实例
         */
        @Bean
        public Advice businessInterceptor(@Qualifier("orderServiceImpl") OrderService orderService) {
            BusinessInterceptor businessInterceptor = new BusinessInterceptor();
            businessInterceptor.setOrderService(orderService);
            return businessInterceptor;
        }
    
        @Bean
        public BeanNameAutoProxyCreator businessInterceptChain() {
            BeanNameAutoProxyCreator creator = new BeanNameAutoProxyCreator();
            creator.setBeanNames("greet*");
            creator.setInterceptorNames("loginInterceptor", "businessInterceptor");
            creator.setProxyTargetClass(true);
            return creator;
        }
    
    }
    
    @Slf4j
    public class BusinessInterceptor implements MethodInterceptor {
    
        private OrderService orderService;
    
        public OrderService getOrderService() {
            return orderService;
        }
    
        public void setOrderService(OrderService orderService) {
            this.orderService = orderService;
        }
    
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            log.info(this.getClass().getSimpleName() + "; " + invocation.getMethod().getName() + " before...");
    
            log.info("执行其他逻辑:" + orderService.totalOrders());
    
            // 通过反射调用目标方法
            Object obj = invocation.proceed();
    
            log.info(this.getClass().getSimpleName() + "; " + invocation.getMethod().getName() + " after...");
            return obj;
        }
    }
    

    3. DefaultAdvisorAutoProxyCreator

    • DefaultAdvisorAutoProxyCreator 扫描容器中的 Advisor, 并将 Advisor 自动织入匹配的目标 Bean 中,即为匹配的目标 Bean 自动创建代理
    @Configuration
    public class BusinessInterceptorConfig {
        @Bean
        public Advisor businessAdvisor() {
            BusinessInterceptor businessInterceptor = new BusinessInterceptor();
            DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
            AnnotationMatchingPointcut pointcut = new AnnotationMatchingPointcut(null, InterceptAnno.class, true);
            advisor.setPointcut(pointcut);
            advisor.setAdvice(businessInterceptor);
            return advisor;
        }
    
        @Bean
        public Advisor business2Advisor() {
            MyInterceptor myInterceptor = new MyInterceptor();
            DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
            AnnotationMatchingPointcut pointcut = new AnnotationMatchingPointcut(null, InterceptAnno.class, true);
            advisor.setPointcut(pointcut);
            advisor.setAdvice(myInterceptor);
            return advisor;
        }
    
        @Bean
        public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
            DefaultAdvisorAutoProxyCreator defaultCreator = new DefaultAdvisorAutoProxyCreator();
            defaultCreator.setAdvisorBeanNamePrefix("business");
            defaultCreator.setUsePrefix(true);
            return defaultCreator;
        }
    
    }
    
    @Slf4j
    public class MyInterceptor implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            log.info(this.getClass().getSimpleName() + "; " + invocation.getThis().getClass().getSimpleName() + "; "
                    + invocation.getMethod().getName());
            return invocation.proceed();
        }
    }
    

    参考

    • 《精通Spring 4.x 企业应用开发实战》

    相关文章

      网友评论

          本文标题:Spring AOP 自动创建代理

          本文链接:https://www.haomeiwen.com/subject/cxuzgdtx.html