2017-02-23 4 views
1
@Transactional 
@Component 
@EntranceLog 
public class TransferServiceImpl implements TransferService { 

    xxxx 

} 

Я hava класс с Transactional аннотация и Component аннотация. EntranceLog - это моя аннотация для печати журнала по aop.Почему не удается получить аннотацию из beanClass?

public class LogProxyCreator extends AbstractAutoProxyCreator implements ApplicationContextAware { 

    private static final LogInterceptor LOG = new LogInterceptor(); 

    private static Logger log = LoggerFactory.getLogger(LogProxyCreator.class); 

    @Override 
    protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String s, TargetSource targetSource) throws BeansException { 
     Annotation anno = null; 

     for (Annotation annotationTemp : beanClass.getAnnotations()) { 
      Log temp = annotationTemp.annotationType().getAnnotation(EntranceLog.class); 
      if (temp != null) { 
       anno = temp; 
       break; 
      } 
     } 

     if (anno == null) { 
      return null; 
     } 
     Object[] additional = new Object[]{LOG}; 

     log.error(beanClass.getName() + " has register the fc log."); 

     return additional; 
    } 

    @Override 
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 
     LOG.setContext(applicationContext); 
    } 
} 

Когда мое приложение начинает, фасоль transferServiceImpl начала, но beanClass.getAnnotations() не может получить какую-либо аннотации. Зачем?

@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.TYPE}) 
@Log(logName = "entrance") 
public @interface EntranceLog { 
    @AliasFor(
     annotation = Log.class, 
     attribute = "subLogName" 
    ) 
    String logName() default ""; 

    @AliasFor(
     annotation = Log.class, 
     attribute = "openInfoLog" 
    ) 
    boolean openInfoLog() default false; 
} 

Это моя аннотация.

+0

Какое определение аннотации? Это даже сохраняется через сборник? – vegaasen

+0

@vegaasen Да, он может сохраняться через компиляцию. Определение аннотации прост. Моя цель состоит в том, чтобы проксировать компонент с аннотацией EntranceLog, но когда приложение запускается, я не могу получить никаких комментариев от компонента. –

+0

Я предлагаю вам добавить код аннотации, возможно, что-то в его определении прекратит его из-за сохраняющегося – niceman

ответ

1

Весной @Transactional уже обработанная аннотация AOP, поэтому для добавления собственных потребуется дополнительная работа. Позвольте мне объяснить, как работает Spring AOP и @Transactional.

Spring имеет два способа сделать АОП, если класс реализует интерфейс он может использовать стандартный JDK Proxy, если класс не реализует интерфейс будет создавать новый подкласс, используя CGLIB испускать байткод во время выполнения , Если вы не будете очень осторожны, вы почти всегда получите прокси-сервер CGLib с Spring AOP.

Когда Spring встречает @Transactional (класс или уровень метода), он создает новый подкласс с использованием CGLib, вы можете думать об этом классе как о декораторе, который пересылает все вызовы вашему классу реализации. До и после (вокруг совета) он проверяет свойства аннотации @Transactional и проверяет, существует ли транзакция на предмет наличия транзакции, если транзакция не создается, и запоминает ее, чтобы потом ее можно было зафиксировать. Если вы установите прерывание внутри метода Transactional и посмотрите на столбец, вы увидите, что вызов вашей реализации пришел из класса декоратора и что для него нет исходного кода.

В вашем случае боба, который добавляется в контексте приложения, это не ваш TransferServiceImpl боб, но CGLIB прокси, созданный весной, когда он нашел @Transactional аннотацию на классе, он будет называться что-то вроде TransferServiceImpl$$FastClassBySpringCGLIB$$<hexstring> - Этот класс не содержит аннотации @EntranceLog, поэтому ваш собственный аспект не работает.

Я никогда не сталкивался с этой проблемой сам, поскольку я стараюсь избегать АОП вообще или всегда на классах, которые уже являются CGLib, проксированными Spring. Если вы не захотите углубиться в источник Spring или найти кого-то из команды Spring Dev, чтобы помочь вам в этом, я предлагаю вам создать еще один слой косвенности, так что вам не нужно обрабатывать два аспекта в одном классе.

+0

Действительно, я должен добавить еще один слой для обработки транзакции, не добавляя 'Transactional' в мою открытую службу. Это отличный ответ для меня, спасибо. –

Смежные вопросы