如何编写类似于ibatis Select注释的弹簧自定义注释?

时间:2018-03-20 02:18:45

标签: java spring annotations customization

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

无论如何,总之,目标是

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

首先看一下结束点 - ArtistNodeRepository.java

@Repository
public interface ArtistNodeRepository {

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

CreateNode注释想要做的事情放在参数Map中。{/ p>

这是注释 - data.put("type", "artist")

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); } } 放到MethodCallbackpostProcessBeforeInitialization的位置。在我的想法中,它将在postProcessAfterInitialization,因为我试图操纵方法的参数

最后,这是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个实例。

我应该如何使用ArtistNodeRepositoryMethodCallback来实现目标?

良好的示例代码将是很好的以及良好的答案。

1 个答案:

答案 0 :(得分:0)

我认为您误解了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();
    }

希望可以帮到你