11、随笔:一个接口多个实现类,如何调用哪个实现类的方法

扯淡

最近在做某“马店”项目中的报表,定时任务(更新报表数据)实现类中使用 @Autowired 注入每张报表的逻辑类。随着报表的增多,@Autowired 越来越多。记录一次使用 ApplicationContextAware 优化的过程。

个人学习总结:
链接:【Java基础、springboot、springcloud、docker 等,学习目录

优化前部分代码:

@Slf4j
@Component
public class ScheduleBox {

    @Autowired
    private DynamicReporterTask dynamicReporterTask;
    
    @Autowired
    private UnitUserWaterTask unitUserWaterTask;
    
    @Autowired
    private AcceptPeriodStatisticsTask acceptPeriodStatisticsTask;

    /* 动态配置报表 */
    //@DistributedLock(lockedKey = "DynamicReporterLock", expireTime = 30)
    @Scheduled(cron = "0/10 * * * * ?")
    public void dynamicReporter() {
        dynamicReporterTask.handle();
    }

    /* 用户登记周期统计表 */
    // @DistributedLock(lockedKey = "AcceptPeriodStatisticsLock", expireTime = 30)
    @Scheduled(cron = "0/10 * * * * ?")
    public void acceptPeriodStatistics() {
        acceptPeriodStatisticsTask.handle();
    }
    
    /* 单位用户用水报表 */
    //@DistributedLock(lockedKey = "UnitUserWaterTaskLock", expireTime = 30)
    @Scheduled(cron = "0/10 * * * * ?")
    public void unitUserWater() {
        unitUserWaterTask.handle();
    }
}

每张报表对应一个task,定时任务中使用 @Autowired 注入。后期报表增加,@Autowired 会越来越多。

优化过程:

主要思路: 提供一个公共的接口,每张报表实现该接口。定时任务从spring容器中获取到对应报表实现类的bean,并使用该公共接口接收。调用接口方法即可。

1、公共接口
/**
 * 报表公共接口
 */
public interface BaseTask {
    public void handle();
}
2、接口实现类

每张报表一个实现类,均实现 BaseTask 接口。

/**
 * 动态配置报表
 */
@Slf4j
@Component
public class DynamicReporterTask implements BaseTask {
	@Override
    public void handle() {
		log.info("+++动态报表处理逻辑");
	}
}
/**
 * 用户登记周期统计表
 */
@Slf4j
@Component
public class AcceptPeriodStatisticsTask implements BaseTask {
	// @Async
    @Override
    public void handle() {
		log.info("+++用户登记周期控制统计表处理逻辑");
	}
}
/**
 * 单位用户用水表
 */
@Slf4j
@Component
public class UnitUserWaterTask  implements BaseTask {
	// @Async
    @Override
    public void handle() {
		log.info("+++单位用户用水报表处理逻辑");
	}
}
3、调用:

获取 spring 容器中接口的具体实现 bean。使用 ApplicationContextAware 接口。

/**
 * 定时任务集合
 * 当一个类实现了接口 ApplicationContextAware 之后,这个类就可以获得 ApplicationContext 中的所有 bean
 */
@Slf4j
@Component
public class ScheduleBox implements ApplicationContextAware {
    
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /* 动态配置报表 */
    //@DistributedLock(lockedKey = "DynamicReporterLock", expireTime = 30)
    @Scheduled(cron = "0/10 * * * * ?")
    public void dynamicReporter() { commonHandle("dynamicReporterTask"); }

    /* 用户登记周期统计表 */
    //@DistributedLock(lockedKey = "AcceptPeriodStatisticsLock", expireTime = 30)
    @Scheduled(cron = "0/10 * * * * ?")
    public void acceptPeriodStatistics() { commonHandle("acceptPeriodStatisticsTask"); }

    /* 单位用户用水报表 */
    //@DistributedLock(lockedKey = "UnitUserWaterTaskLock", expireTime = 30)
    @Scheduled(cron = "0/10 * * * * ?")
    public void unitUserWater() { commonHandle("unitUserWaterTask"); }

    /**
     * 公共处理方法
     * @param bean BaseTask 接口实现类在 spring 容器中的名称
     */
    private void commonHandle(String bean) {
        BaseTask reporterTask = (BaseTask) applicationContext.getBean(bean);
        reporterTask.handle();
    }
}

ApplicationContextAware 接口:
spring 容器在初始化时,如果Spring配置文件中所定义的Bean实现了该接口,那么加载时会调用 setApplicationContext(ApplicationContext applicationContext) throws BeansException 方法,获得ApplicationContext对象。通过ApplicationContext对象就可以获取具体的实现类。

总结:

获取一个接口具体哪个实现类的方式
1、new 一个具体的接口实现类对象。
2、@Autowired 注入具体实现类。
3、使用 @Resource 注解指定实现类名称。

@Resource(name = "dynamicReporterTask")
private BaseTask baseTask;

4、@Qualifier 指定

@Autowired
@Qualifier("dynamicReporterTask")
private BaseTask baseTask;

5、ApplicationContextAware 接口。

问题:
项目常分 controller、service、dao 层。其中service层分“接口” 和 “Impl” 层,其中接口层有必要吗?
个人认为,当接口只有一个实现类的时时候,那么接口层就没必要了。service分两层有一个重要的原因,尼玛代码生成器已经帮我们把接口生成了。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
很抱歉,作为一名 AI,我无法生成实际可用的网页代码。但是,你可以通过以下步骤自己创建一个简单的书城网页首页: 1. 编写 HTML 结构,包括头部、导航栏、轮播图、分展示、推荐书籍等模块。 ``` <!DOCTYPE html> <html> <head> <title>书城首页</title> <meta charset="utf-8"> <link rel="stylesheet" href="style.css"> </head> <body> <header> <h1>书城</h1> <nav> <a href="#">首页</a> <a href="#">分</a> <a href="#">购物车</a> <a href="#">我的</a> </nav> </header> <main> <div class="carousel"> <img src="carousel1.jpg" alt="轮播图1"> <img src="carousel2.jpg" alt="轮播图2"> <img src="carousel3.jpg" alt="轮播图3"> </div> <div class="categories"> <h2>分</h2> <a href="#">小说</a> <a href="#">散文随笔</a> <a href="#">传记</a> <a href="#">哲学</a> <a href="#">历史</a> </div> <div class="recommendations"> <h2>推荐</h2> <div class="book"> <img src="book1.jpg" alt="书籍1"> <h3>书籍1</h3> <p>简介1</p> <p>价格1</p> </div> <div class="book"> <img src="book2.jpg" alt="书籍2"> <h3>书籍2</h3> <p>简介2</p> <p>价格2</p> </div> <div class="book"> <img src="book3.jpg" alt="书籍3"> <h3>书籍3</h3> <p>简介3</p> <p>价格3</p> </div> </div> </main> <footer> <p>© 2021 书城</p> </footer> </body> </html> ``` 2. 编写 CSS 样式,美化页面,使其更加吸引人。 ``` body { font-family: Arial, sans-serif; margin: 0; padding: 0; } header { background-color: #333; color: #fff; display: flex; justify-content: space-between; padding: 10px 20px; } nav { display: flex; } nav a { color: #fff; margin-left: 20px; text-decoration: none; } nav a:hover { text-decoration: underline; } main { padding: 20px; } .carousel { display: flex; justify-content: space-between; overflow: hidden; } .carousel img { width: 100%; } .categories { margin-top: 20px; } .categories h2 { font-size: 20px; } .categories a { display: block; margin-top: 10px; text-decoration: none; } .recommendations { margin-top: 20px; } .recommendations h2 { font-size: 20px; } .book { background-color: #eee; border-radius: 5px; display: inline-block; margin-right: 20px; padding: 10px; width: 200px; } .book img { width: 100%; } .book h3 { font-size: 16px; margin-top: 10px; } .book p { margin: 0; } footer { background-color: #333; color: #fff; padding: 10px 20px; text-align: center; } ``` 3. 在服务器上部署网页,使用户能够访问到。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值