gpt4 book ai didi

java - 为什么添加父类(super class)会破坏我的 Spring bean?

转载 作者:搜寻专家 更新时间:2023-11-01 02:57:13 27 4
gpt4 key购买 nike

我有一个正常工作的 Spring Boot Web 应用程序。我注意到两个 @Repository bean 有很多共同点,所以我使用抽象父类(super class)重构了它们,现在我的应用程序坏了。我仔细检查过,这是我在工作状态和非工作状态之间所做的唯一更改。谁能看出我做错了什么?

这是我的工作代码:

public class One { ... }
public class Two { ... }

@Repository
public class RepoOne {
private final ISource<One> sourceOne;
private ICache<One> cache;
@Value("${com.example.lifetime.one}")
private int lifetime;
public RepoOne(ISource<One> sourceOne) {
this.sourceOne = sourceOne;
}
@PostConstruct
public void createCache() {
Duration lifetime = Duration.ofMinutes(this.lifetime);
this.cache = new Cache<>(lifetime, sourceOne);
}
public One get(String key) {
return cache.get(key);
}
}

@Repository
public class RepoTwo {
private final ISource<Two> sourceTwo;
private ICache<Two> cache;
@Value("${com.example.lifetime.two}")
private int lifetime;
public RepoOne(ISource<Two> sourceTwo) {
this.sourceTwo = sourceTwo;
}
@PostConstruct
public void createCache() {
Duration lifetime = Duration.ofMinutes(this.lifetime);
this.cache = new Cache<>(lifetime, sourceTwo);
}
public Two get(String key) {
return cache.get(key);
}
}

@Service
public class RepoService {
private final RepoOne repoOne;
private final RepoTwo repoTwo;
public RepoService(RepoOne repoOne, RepoTwo repoTwo) {
this.repoOne = repoOne;
this.repoTwo = repoTwo;
}
public void doSomething(String key) {
One one = repoOne.get(key);
...
}
}

这是我重构的代码,我在其中引入了一个抽象的通用父类(super class)。

abstract class AbstractRepo<T> {
private final ISource<T> source;
private ICache<T> cache;
AbstractRepo (ISource<T> source) {
this.source = source;
}
@PostConstruct
private void createCache() {
Duration lifetime = Duration.ofMinutes(lifetime());
this.cache = new Cache<>(lifetime, source);
}
protected abstract int lifetime();
public final T get(String key) {
return cache.get(key);
}
}

@Repository
public class RepoOne extends AbstractRepo<One> {
@Value("${com.example.lifetime.one}")
private int lifetime;
public RepoOne(ISource<One> sourceOne) {
super(source);
}
protected int lifetime() { return lifetime; }
}

@Repository
public class RepoTwo extends AbstractRepo<Two> {
@Value("${com.example.lifetime.two}")
private int lifetime;
public RepoTwo(ISource<Two> sourceTwo) {
super(source);
}
protected int lifetime() { return lifetime; }
}

当使用重构代码时,我在 AbstractRepo::get() 中得到了一个 NullPointerException。我已通过调试器确认 cachenull(以及 source)。但是,我还通过调试器确认创建了 RepoOne 和 RepoTwo 的实例并调用了它们的 createCache() 方法。就好像正在创建每个实例的两个实例,并且只有一个实例被初始化。有什么想法吗?

最佳答案

不是你引入了父类,而是你把get方法变成了final方法。

@Repository 注释的类将获得自动异常转换。这种自动异常转换是通过使用 AOP 添加的。在 Spring 中应用 AOP 的默认机制是使用代理,在本例中是基于类的代理。

发生的事情是 CgLib 通过子类化为您的类创建代理,以便在调用方法时可以添加通知。但是 final 方法不能在子类中被覆盖。这将导致在代理而不是实际实例上调用 get 方法。

有两种方法可以解决这个问题

  1. 删除 final 关键字
  2. 引入一个接口(interface)来为您的存储库定义契约。这将导致创建 JDK 动态代理。 JDK 动态代理是基于接口(interface)的,不需要子类化您的实际类(仅适用于基于类的代理)。

关于java - 为什么添加父类(super class)会破坏我的 Spring bean?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52639160/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com