请教 Java 类继承问题

2021-11-22 17:00:35 +08:00
 heyjude321
@Service
public class AuthUserService {
@Autowired
private AuthUserDao authUserDao;

// ----> start
public static AuthUserService self;

@Autowired
public void setService(AuthUserService authUserService) {
AuthUserService.self = authUserService;
}
// ---> end 这部分我想用 BaseService 之类的复用继承
}

public interface AuthUserDao extends JpaRepository<AuthUser, Long> {

}

我的目的是能通过 AuthUserService .self.functionName() 之类的直接通过类名调用 service 的方法。
各位 V 友,请教该怎么写 BaseService ,或者有没有更好的方案?
2595 次点击
所在节点    Java
23 条回复
chendy
2021-11-22 17:22:11 +08:00
目测做不到,因为 static 上下文里没有 this 这个东西,于是除非手动覆盖否则都是走父类的
如果需求是在静态上下文里取 bean 然后调用方法的话,用 ApplicationContextAware 做一个入口就可以
chenshun00
2021-11-22 17:40:14 +08:00
1 、什么需求促使你要这么写?

2 、如果炫技大可不必,如果不是炫技,可以用下模板模式?
heyjude321
2021-11-22 17:52:59 +08:00
@chenshun00 1.为了让枚举方法里可以使用 service 的方法。2.不是炫技。
aragakiyuii
2021-11-22 19:00:04 +08:00
如果在启动的时候不使用 AuthUserService ,那可以在枚举里声明 AuthUserService ,然后写个 ApplicationRunner 或者 CommandLineRunner 或者 configuration 手动 set 一下
ccde8259
2021-11-22 19:05:57 +08:00
@heyjude321 实现 ApplicationListener<ApplicationStartedEvent>,在 onApplicationEvent(ApplicationStartedEvent)方法里面拿 ApplicationContext 写入 本类的 static 域。开一个 static 方法 T getBean(Class<T>)给枚举类用。
ccde8259
2021-11-22 19:13:16 +08:00
不太确定下述写法能否过编译:

class <T> BaseService<T extends BaseService> {
protected T self;
@PostConstruct
public void injectSelf(T t){
this.self=t;
}
}
class BaseServiceImpl extends BaseService<BaseServiceImpl> {
}
ccde8259
2021-11-22 19:16:47 +08:00
@ccde8259 应该是自限定类型 也就是 class <T> BaseService<T extends BaseSevice<T>>
chrisia
2021-11-22 20:31:21 +08:00
applicationContext.getBean
dranfree
2021-11-23 09:46:32 +08:00
初始化完成之后从 Spring 容器里面取出本类的 bean 然后赋值给静态字段即可,不过一般不这样写,不伦不类的
wolfie
2021-11-23 15:44:17 +08:00
用 static 不能。
BaseService 维护一个 map 可以。

public abstract class BaseService<T extends BaseService<?>> {

private static final Map<Class<?>, BaseService<?>> map = new ConcurrentHashMap<>();

public BaseService() {
map.put(this.getClass(), this);
}

T self() {
return (T) map.get(this.getClass());
}

}
goalidea
2021-11-23 16:48:06 +08:00
如果是枚举里使用 service 简单的方法是 hutool 工具里的 SpringUtil
heyjude321
2021-11-24 10:05:38 +08:00
@ccde8259
这样不能通过 AuthUserService.self 进行引用,因为 self 不是静态的。
通过 ApplicationListener 吗?不确定你的方案是什么,但我尝试了本帖其他答主类似的方法,如果父类有 static 方法,则返回值用不了泛型。public static T getSelf() 会报错。
heyjude321
2021-11-24 10:16:21 +08:00
@aragakiyuii 枚举里怎么声明 AuthUserService ?
EMAIL_PASSWORD("邮箱+密码") {
@Autowired
AuthUserService authUserService;

@Override
public Result isExist(LoginVO loginVO) {
return super.isExist(loginVO);
}

@Override
public Result isPassAuth(LoginVO loginVO) {
return super.isPassAuth(loginVO);
}

@Override
public Result register(LoginVO loginVO) {
return super.register(loginVO);
}
};
这样不行呐,authUserService 是 null
heyjude321
2021-11-24 10:17:23 +08:00
@wolfie self() 不是 static 的,没办法用过 AuthUserService.self()进行引用。
heyjude321
2021-11-24 10:21:09 +08:00
@dranfree 好像不行。
父类里写:
public static T self;
不能通过编译。
wolfie
2021-11-24 10:30:24 +08:00
@heyjude321 #14
static <T> T self(Class<T> clazz) {
return (T) map.get(clazz);
}
dranfree
2021-11-24 11:10:26 +08:00
@heyjude321 啊,你为什么要用泛型,Java 里面静态字段是和对象绑定的
dranfree
2021-11-24 11:15:20 +08:00
@heyjude321

```java
@Component
public class DemoServiceImpl implements DemoService, ApplicationContextAware {

public static DemoService self;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
DemoServiceImpl.self = applicationContext.getBean(DemoService.class);
}

@Override
public String echo(String message) {
return message;
}
}
```
dranfree
2021-11-24 11:18:45 +08:00
@dranfree 至于复用继承,应该是不可行的,因为静态字段和类绑定
dranfree
2021-11-24 11:26:43 +08:00
@dranfree 这里说错了,应该是字段泛型和对象绑定的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/817175

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX