请教 Java 类继承问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
heyjude321
V2EX    Java

请教 Java 类继承问题

  •  
  •   heyjude321 2021-11-22 17:00:35 +08:00 3051 次点击
    这是一个创建于 1448 天前的主题,其中的信息可能已经有所发展或是发生改变。
    @Service
    public class AuthUserService {
    @Autowired
    private AuthUserDao authUserDao;

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

    @a target="_blank" href="/member/Autowired" rel="nofollow noopener">Autowired
    public void setService(AuthUserService authUserService) {
    AuthUserService.self = authUserService;
    }
    // ---> end 这部分我想用 BaseService 之类的复用继承
    }

    public interface AuthUserDao extends JpaRepository<AuthUser, Long> {

    }

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

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

    class <T> BaseService<T extends BaseService> {
    protected T self;
    @PostConstruct
    public void injectSelf(T t){
    this.self=t;
    }
    }
    class BaseServiceImpl extends BaseService<BaseServiceImpl> {
    }
    ccde8259
        7
    ccde8259  
       2021-11-22 19:16:47 +08:00 via iPhone
    @ccde8259 应该是自限定类型 也就是 class <T> BaseService<T extends BaseSevice<T>>
    chrisia
        8
    chrisia  
       2021-11-22 20:31:21 +08:00
    applicationContext.getBean
    dranfree
        9
    dranfree  
       2021-11-23 09:46:32 +08:00
    初始化完成之后从 Spring 容器里面取出本类的 bean 然后赋值给静态字段即可,不过一般不这样写,不伦不类的
    wolfie
        10
    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
        11
    goalidea  
       2021-11-23 16:48:06 +08:00
    如果是枚举里使用 service 简单的方法是 hutool 工具里的 SpringUtil
    heyjude321
        12
    heyjude321  
    OP
       2021-11-24 10:05:38 +08:00
    @ccde8259
    这样不能通过 AuthUserService.self 进行引用,因为 self 不是静态的。
    通过 ApplicationListener 吗?不确定你的方案是什么,但我尝试了本帖其他答主类似的方法,如果父类有 static 方法,则返回值用不了泛型。public static T getSelf() 会报错。
    heyjude321
        13
    heyjude321  
    OP
       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
        14
    heyjude321  
    OP
       2021-11-24 10:17:23 +08:00
    @wolfie self() 不是 static 的,没办法用过 AuthUserService.self()进行引用。
    heyjude321
        15
    heyjude321  
    OP
       2021-11-24 10:21:09 +08:00
    @dranfree 好像不行。
    父类里写:
    public static T self;
    不能通过编译。
    wolfie
        16
    wolfie  
       2021-11-24 10:30:24 +08:00
    @heyjude321 #14
    static <T> T self(Class<T> clazz) {
    return (T) map.get(clazz);
    }
    dranfree
        17
    dranfree  
       2021-11-24 11:10:26 +08:00
    @heyjude321 啊,你为什么要用泛型,Java 里面静态字段是和对象绑定的
    dranfree
        18
    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
        19
    dranfree  
       2021-11-24 11:18:45 +08:00
    @dranfree 至于复用继承,应该是不可行的,因为静态字段和类绑定
    dranfree
        20
    dranfree  
       2021-11-24 11:26:43 +08:00
    @dranfree 这里说错了,应该是字段泛型和对象绑定的
    aragakiyuii
        21
    aragakiyuii  
       2021-11-24 13:09:43 +08:00
    ccde8259
        22
    ccde8259  
       2021-11-24 13:59:18 +08:00 via iPhone
    @heyjude321 ApplicationListener 是用于捕获 ApplicationContext 的。捕获并置入 static 域后才能被 static 的 getBean 方法调用。
    heyjude321
        23
    heyjude321  
    OP
       2021-11-25 10:58:11 +08:00
    @ccde8259
    @aragakiyuii
    @dranfree
    @wolfie
    谢谢各位 V 友的回答,给了我一些启发。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     875 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 22:26 PVG 06:26 LAX 14:26 JFK 17:26
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86