【问题标题】:How to code spring custom annotation which works like ibatis Select annotation?如何编写类似于 ibatis Select 注释的 spring 自定义注释?
【发布时间】:2018-03-20 02:18:45
【问题描述】:

我正在尝试制作像 ibatis @Select 这样的自定义注释。

总之,目标是

  • 将一些数据附加到方法具有自定义注释的参数中

先看看终点——ArtistNodeRepository.java

@Repository
public interface ArtistNodeRepository {

    @CreateNode(tid = "artist")
    public Node create(Map data) throws Exception;
}

CreateNode注解的作用是将data.put("type", "artist")放入参数Map中。

这里是注解 - CreateNode.java

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface CreateNode {
    String[] values() default "";
    String tid();
}

为了控制器注解,我准备了这个BeanPostProcessor - NodeAnnotationProcessor.java

@Component
public class NodeAnnotationProcessor implements BeanPostProcessor {

    private ConfigurableListableBeanFactory configurableListableBeanFactory;

    @Autowired
    public NodeAnnotationProcessor(ConfigurableListableBeanFactory configurableListableBeanFactory) {
        super();
        this.configurableListableBeanFactory = configurableListableBeanFactory;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        this.scanNodeAnnotation(bean, beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
       // this.scanNodeAnnotation(bean, beanName);
        return bean;
    }

    protected void scanNodeAnnotation(Object bean, String beanName){
        this.configureMethodAction(bean);
    }

    private void configureMethodAction(Object bean){
        Class<?> managedBeanClass = bean.getClass();
        ReflectionUtils.MethodCallback methodCallback = new NodeMethodCallback(configurableListableBeanFactory, bean);
        ReflectionUtils.doWithMethods(managedBeanClass, methodCallback);
    }
}

我不清楚将MethodCallback 放在postProcessBeforeInitializationpostProcessAfterInitialization 的哪个位置。在我看来,它应该在after,因为我正在尝试操纵方法的参数

最后,这是MethodCallback - NodeMethodCallback.java

public class NodeMethodCallback implements ReflectionUtils.MethodCallback {

    private Logger logger = LoggerFactory.getLogger(NodeMethodCallback.class);

    private ConfigurableListableBeanFactory beanFactory;
    private Object bean;
    private static int AUTOWIRE_MODE = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;

    public NodeMethodCallback(ConfigurableListableBeanFactory beanFactory, Object bean) {
        this.beanFactory = beanFactory;
        this.bean = bean;
    }

    @Override
    public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {

        logger.info("doWith method info :: " + String.valueOf(bean) + "." + bean.getClass().getName());
        /*
            What I expected is Printing ArtistNodeRepository Class with create Method
            But It prints something like ...

            SessionFlashMapManager
            DefaultRequestToViewNameTranslator
            ...
        */


        try {
           logger.info("When I call you :: " + method.getName()); // I expect method which contains @CreateNode annotation, but it is not ...
            Annotation[] methodAnnotations = method.getDeclaredAnnotations();
            boolean isTarget = false;
            String tid = "";
            for(Annotation anno : methodAnnotations) {
                logger.info("annotation Class :: " + anno.getClass().getName());
                if(isTarget) break;
                if(anno instanceof CreateNode) {
                    logger.info("CreateNode annotation found");
                    CreateNode createNode = method.getDeclaredAnnotation(CreateNode.class);
                    tid = createNode.tid();
                    isTarget = true;
                } 
            }
            if(!isTarget) return;
            ReflectionUtils.makeAccessible(method);

            /*
                Do Somthing with Parameter ...
                Do Somthing with Parameter ...
                Do Somthing with Parameter ...
                Do Somthing with Parameter ...
                Do Somthing with Parameter ...
            */
        } catch (Exception e ){
            logger.error("ERROR", e);
        }
    }
}

问题是...在doWith 中我找不到ArtistNodeRepository 实例。

我应该如何处理MethodCallbackBeanPostProcessor 来实现目标?

好的示例代码和好的答案一样好。

【问题讨论】:

    标签: java spring annotations customization


    【解决方案1】:

    我认为您误解了ReflectionUtils.doWithMethods 的用法。这意味着如果匹配回调,则迭代类方法。而不是在调用方法回调时。

      public static void doWithMethods(Class<?> clazz, MethodCallback mc, MethodFilter mf) {
            // Keep backing up the inheritance hierarchy.
            Method[] methods = getDeclaredMethods(clazz);
            for (Method method : methods) {
                if (mf != null && !mf.matches(method)) {
                    continue;
                }
                try {
                    mc.doWith(method);
                }
                catch (IllegalAccessException ex) {
                    throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
                }
            }
            if (clazz.getSuperclass() != null) {
                doWithMethods(clazz.getSuperclass(), mc, mf);
            }
            else if (clazz.isInterface()) {
                for (Class<?> superIfc : clazz.getInterfaces()) {
                    doWithMethods(superIfc, mc, mf);
                }
            }
        }
    

    我认为你可以使用方面。像这样。

        @Around("execution(public * org.springframework.data.jpa.repository.JpaRepository+.*(..))")
        // @Around("@annotation(Repository)")
        public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            CreateNode createNode = method.getAnnotation(CreateNode.class);
            if(createNode != null) {
                Object[] args = joinPoint.getArgs();
                // do your business
    
            }
            return joinPoint.proceed();
        }
    

    希望能帮到你

    猜你喜欢
    • 2021-06-26
    • 2018-02-06
    • 2020-09-10
    • 1970-01-01
    • 2020-02-14
    • 1970-01-01
    • 2019-12-24
    • 2016-06-03
    • 1970-01-01
    相关资源
    最近更新 更多