java - Spring CGLib 代理 - 类变量变为空
问题描述
我有一个过滤器服务,其方法通过方面进行分析。作为一个例子,我会给你一段我有问题的代码
@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调用了我的方法,在调试器中我已经看到了这个- FilterService$$EnhancerBySpringCGLIB我的类中的所有变量都是空的,所以我得到空指针异常。
如果 CGLIb 似乎通过继承工作,为什么会这样?以及为什么在第一个方法(filterItems)中这个- 是一个没有 CGlib 的类,但是当你从它调用另一个方法(filterItems -> initNotSpecificFilters)时,cglib 已经出现了。
解决方案
问题是动态代理,不管是JDK接口代理还是CGLIB类代理,都只能继承
- 公共方法(JDK、CGLIB)或
- 受保护的和包范围的方法(仅限 CGLIB)。
此外,代理不继承任何实例变量值,因为这不是它们的目的,它们只包装方法并调用原始方法,并可能在方面建议或拦截器之前和之后调用。
现在你的情况如下:
您的方法
initNonSpecificFilters(..)
是私有的。也就是说,如果你调用它self
,你实际上仍然会调用原始方法(因为它没有被包装),但是代理的成员当然没有值。顺便说一句,该方法是私有的这一事实也是为什么如果您有一个针对该方法的切入点,则 Spring AOP 方面不会为该方法启动(使用 AspectJ 会有所不同)。
在Spring 手册中搜索术语self-invocation,该行为有很好的记录。
您的问题的解决方案是使该方法成为非私有方法。
推荐阅读
- android - 从 Chrome 重定向到带有位置标头的 302 后被阻止的 Android 应用
- angular - 如何从中获取纯文本
使用表单控件?我无法得到它。文本保存在 xyz
福尔梅 - javascript - 防止全屏菜单滚动
- java - 如何将 JUnit 测试从一个 Maven 项目导入另一个?
- ios - 在堆栈视图中带有堆栈视图的水平集合视图在重新加载动画时隐藏内部堆栈视图
- java - Wildfly 9.0 中部署 java 战争(用 jaxrs 编写的其余 api)的问题
- azure - Access ADLS2 from PowerBI service with Guest user credentials
- python - 在 Python 中将循环小数转换为分数
- python - 检索 google play 评论时发生 Selenium Webdriver 异常
- python - IntelliJ django unittests '应用程序未加载'