package com.elab.spring.config;

import com.elab.spring.intercept.annotation.AnnotationAttributeSourcePointcut;
import com.elab.spring.intercept.annotation.AnnotationInterceptor;
import com.elab.spring.intercept.annotation.AnnotationProcessService;
import org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;

import java.util.List;

/**
 * 对于拦截器的一些定义
 *
 * @author liukaixiong
 * @Email liukx@elab-plus.com
 * @date 2021/9/27 - 11:02
 */
@Configuration
public class AopConfig {

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    @ConditionalOnBean(AnnotationProcessService.class)
    public DefaultBeanFactoryPointcutAdvisor transactionAdvisor(
        AnnotationAttributeSourcePointcut annotationAttributeSourcePointcut) {
        DefaultBeanFactoryPointcutAdvisor advisor = new DefaultBeanFactoryPointcutAdvisor();
        // 具体的拦截器
        advisor.setAdvice(annotationInterceptor());
        // 需要被拦截方法的规则判断器，一旦符合，才会被代理给拦截器处理
        advisor.setPointcut(annotationAttributeSourcePointcut);
        return advisor;
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    @ConditionalOnBean(AnnotationProcessService.class)
    public AnnotationAttributeSourcePointcut annotationAttributeSourcePointcut(
        List<AnnotationProcessService> annotationProcessServiceList) {
        // 该类是用作比对方法的注解是否符合代理的条件
        AnnotationAttributeSourcePointcut cacheAttributeSourcePointcut = new AnnotationAttributeSourcePointcut();
        annotationProcessServiceList.forEach((annotation) -> {
            cacheAttributeSourcePointcut.addAnnotations(annotation.annotation());
        });
        return cacheAttributeSourcePointcut;
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    @ConditionalOnBean(AnnotationProcessService.class)
    public AnnotationInterceptor annotationInterceptor() {
        AnnotationInterceptor interceptor = new AnnotationInterceptor();
        return interceptor;
    }
}
