Spring CGLib代理-类变量变为null

3

我有一个过滤器服务,其方法通过切面进行分析。我会给你一个代码片段作为例子,其中我遇到了一个问题。

    @Service
    public class FilterService extends AbstractService {
        private static final Logger log = LoggerFactory.getLogger(FilterService.class);

        @Autowired
        //Proxy to profiling class
        private FilterService self;

        private final ItemsRepository itemsRepository;
        private final Map<String, EnumFilter> enumFilters;

        public FilterService(ReadWriteLock readWriteLock,
                             ItemsRepository itemsRepository,
                             CategoryRepository categoryRepository, ItemsMapper itemsMapper,
                             CharacteristicsRepository characteristicsRepository,
                             List<EnumFilter> enumFilters) {
            super(readWriteLock.readLock());
            this.itemsRepository = itemsRepository;
            this.enumFilters = enumFilters.stream().collect(Collectors.toMap(EnumFilter::getId, y -> y));
        }

        @Profileable
        public ItemsViewShared filterItems(@Nullable String categoryId,
                                           @NotNull Set<String> ids,
                                           @NotNull Lang lang,
                                           @NotNull SortType sortType,
                                           @NotNull FilterInfo filterInfo) {
            try {
                this.readLock.lock();
                final ItemsViewShared itemsViewResponse = new ItemsViewShared(); //in this line inspector show this = FilterService

                List<Filter> allFilters = self.initNonSpecificFilters(lang, filterInfo); //problem is here
      //some code...

    @Profileable
    private List<Filter> initNonSpecificFilters(@NotNull Lang lang, @NotNull FilterInfo filterInfo) {
        final List<NumericFilter> allNumericNonSpecific = NumericFilter.getAllNonSpecific(lang, filterInfo);

       //in this line enumFilters - null
        final List<EnumOptionFilter> allEnumNonSpecific = enumFilters.values().stream()
                .flatMap(x -> x.getAllOptions(lang, filterInfo).stream())
                .collect(Collectors.toList());

据我所知,默认情况下,如果类没有继承至少一个方法的接口,将使用CGlib代理,并且Cglib通过继承工作。问题是:当我从控制器调用filterItems方法时,在这个方法中调试器显示this-FilterService。在这个方法中,还会调用此类的另一个需要进行分析的方法。为了让代理工作,我需要进行自身自动装配。之后,我通过self.initNonSpecificFilters来调用我的方法,在调试器中我已经看到this-FilterService$$EnhancerBySpringCGLIB,而我类中的所有变量都是null,因此我得到空指针异常。

为什么如此,如果CGLib似乎通过继承工作?为什么第一个方法(filterItems)中的this是没有使用CGlib的类,但是当您从其中调用另一个方法(filterItems -> initNotSpecificFilters)时,cglib就出现了呢?

1个回答

5
问题在于动态代理,无论是JDK接口代理还是CGLIB类代理,只继承公共方法(JDK、CGLIB)或受保护的和包范围的方法(仅限CGLIB)。此外,代理不会继承任何实例变量值,因为这不是它们的目的,它们只是包装方法并调用原始方法,可能会在前后方面通知或拦截器中添加一些内容。现在您的情况如下:您的方法initNonSpecificFilters(..)是私有的。也就是说,如果您在self上调用它,您实际上仍然会调用原始方法(因为它没有被包装),但代理的成员当然没有任何值。顺便说一句,该方法为私有方法,这也是为什么如果您有一个针对该方法的切入点,Spring AOP方面不会为该方法启动的原因(使用AspectJ则会有所不同)。请在Spring手册中搜索“自我调用”一词,行为得到了很好的记录。
解决您的问题的方法是将该方法改为非私有方法。

谢谢。的确,我没有考虑到私有方法。 - Peter Kozlovsky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接