Spring CGLib 代理 - class 变量变为空
Spring CGLib proxy - class variables become null
我有一个过滤服务,其方法通过方面进行概要分析。作为例子,我会给你一段我遇到问题的代码
@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());
据我所知,默认情况下,如果 class 没有通过至少一种方法继承接口,将使用 CGlib 代理,Cglib 通过继承工作。
问题是这样的:当我从控制器调用 filterItems 方法时,调试器在此方法中显示 this - 过滤服务.
此外,在这种方法中,另一种方法 class 也应该被分析。为了让代理工作,我需要自动装配。之后我通过 self.initNonSpecificFilters 调用了我的方法,在调试器中我已经看到 this - FilterService$$ EnhancerBySpringCGLIB 和我的 class 中的所有变量都是空的,所以我得到空指针异常。
为什么会这样,如果 CGLIb 似乎是通过继承工作的?以及为什么在第一个方法(filterItems)中 this - 是一个没有 CGlib 的 class,但是当你从它调用另一个方法(filterItems -> initNotSpecificFilters)时,cglib 已经出现了。
问题是动态代理,无论JDK接口代理还是CGLIBclass代理,都只继承
- public 方法(JDK、CGLIB)或
- 受保护和包范围内的方法(仅限 CGLIB)。
此外,代理不继承任何实例变量值,因为这不是它们的目的,它们只是环绕方法并调用原件加上可能在方面建议或拦截器之前和之后。
现在您的情况如下:
您的方法 initNonSpecificFilters(..)
是私有的。 IE。如果你在 self
上调用它,你实际上仍然会调用原始方法(因为它没有被包装),但是代理的成员当然没有值。
顺便说一句,该方法是私有的这一事实也是为什么 Spring AOP 方面不会启动该方法,如果您有一个切入点(使用 AspectJ 它将是不同)。
在 Spring manual 中搜索术语 self-invocation,该行为已详细记录。
您的问题的解决方案是使方法非私有。
我有一个过滤服务,其方法通过方面进行概要分析。作为例子,我会给你一段我遇到问题的代码
@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());
据我所知,默认情况下,如果 class 没有通过至少一种方法继承接口,将使用 CGlib 代理,Cglib 通过继承工作。
问题是这样的:当我从控制器调用 filterItems 方法时,调试器在此方法中显示 this - 过滤服务.
此外,在这种方法中,另一种方法 class 也应该被分析。为了让代理工作,我需要自动装配。之后我通过 self.initNonSpecificFilters 调用了我的方法,在调试器中我已经看到 this - FilterService$$ EnhancerBySpringCGLIB 和我的 class 中的所有变量都是空的,所以我得到空指针异常。
为什么会这样,如果 CGLIb 似乎是通过继承工作的?以及为什么在第一个方法(filterItems)中 this - 是一个没有 CGlib 的 class,但是当你从它调用另一个方法(filterItems -> initNotSpecificFilters)时,cglib 已经出现了。
问题是动态代理,无论JDK接口代理还是CGLIBclass代理,都只继承
- public 方法(JDK、CGLIB)或
- 受保护和包范围内的方法(仅限 CGLIB)。
此外,代理不继承任何实例变量值,因为这不是它们的目的,它们只是环绕方法并调用原件加上可能在方面建议或拦截器之前和之后。
现在您的情况如下:
您的方法
initNonSpecificFilters(..)
是私有的。 IE。如果你在self
上调用它,你实际上仍然会调用原始方法(因为它没有被包装),但是代理的成员当然没有值。顺便说一句,该方法是私有的这一事实也是为什么 Spring AOP 方面不会启动该方法,如果您有一个切入点(使用 AspectJ 它将是不同)。
在 Spring manual 中搜索术语 self-invocation,该行为已详细记录。
您的问题的解决方案是使方法非私有。