我以前用过春天。我搬到了一个不同的团队,在那里我逐渐熟悉了代码基。我找到了下面的代码,并试图了解它是如何工作的,以及spring如何在这种情况下注入自动配置的对象。从我关于Spring的基本知识来看,这绝对不是正确的方法。但令人惊讶的是,这段代码已经制作了很长时间,没有发现任何问题。
@Controller
@RequestMapping("/start")
public class AController implements Runnable, InitializingBean {
@Autowired
private StartServiceImpl service = new StartServiceImpl(); // 1
Thread thread;
public void run() {
service.start();
}
public void stop() {
try {
thread.join();
} catch (InterruptedException e) {
}
}
}
@Override
public void afterPropertiesSet() throws Exception {
thread = new Thread(this);
thread.setPriority(Thread.MAX_PRIORITY);
thread.start();
}
}
@Component
public class StartServiceImpl {
//methods
}( Q1) localhost:8080/project/start应该做什么。没有定义GET或POST方法。
( Q2)在注释的第1行上,StartServiceImpl是自动生成的,并且使用"new“构造。所以这里发生了什么。容器是注入bean还是只是一个对象被实例化。
@Controller
@RequestMapping("/stop")
public class BController {
@Autowired
private StartServiceImpl service = new StartServiceImpl();
@RequestMapping(value = "**", method = RequestMethod.GET)
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
service.shutdownRequested();
new AController().stop(); // 2
} catch (Exception e) {
}
}
}( Q3)在注释的第2行中,是否调用stop,在应用程序上下文中调用bean上的stop,或者创建一个新对象并调用stop方法。在后一种情况下会发生什么?我们真的停止了已经启动的服务吗?我认为我们不会停止这项服务。
我读过this post。它非常有用。但它没有回答我的问题。
发布于 2016-06-09 06:11:31
我将尝试具体地回答这些问题,因为代码的目的很难理解(至少对我来说是这样)。
Q1)对我来说,这段代码试图实现什么还不清楚。正如您注意到的,它不是控制器,我怀疑它以这种方式注册的唯一原因是能够自动扫描(这也可以通过@Controller完成)。这只是一种预感,我不太明白它的目的。
Q2)答案是,将创建两个实例,一个通过new创建,另一个作为bean创建。在Spring中运行时,字段的最终值是bean,因为依赖注入发生在构造之后。通常,当类被设想在Spring之外使用时(例如,单元测试),这是这样做的,这样可以用默认值初始化字段。
Q3) stop()将在新实例上调用,而不是在bean上调用。由于该行上面对注入bean的直接调用,服务bean被停止,但我想下一个调用将是NPE,因为afterPropertiesSet不会在通过new创建的目标对象上调用。这没有在日志中显示NPE的唯一原因是因为下面的异常被吞没了。thread变量未初始化,仍然为空。
希望这能帮上忙
发布于 2016-06-09 06:25:58
此代码在许多级别上都存在缺陷。
我会让线程一直运行, annotation,并使用控制器切换一个标志,以决定线程是否真的做了一些事情。
@Service
class StartService{
private boolean active;
public void setActive(boolean active){this.active=active;}
@Scheduled(fixedRate=5000)
public void doStuff(){
if(!active)return;
// do actual stuff here
}
}现在rest控制器所做的就是切换"active“字段的值。好处:
发布于 2016-06-09 06:26:36
你发布的代码很奇怪。
Q1 )本地主机:8080/project/start预期会做什么。没有定义GET或POST方法。
我认为localhost:8080/project/start将返回404错误(请求的资源不可用)。因为AController中没有映射的方法。类级的@RequestMapping注释不足以向控制器发出请求。必须有映射方法。
但是服务还是会开始的。因为AController实现了InitializingBean。在创建控制器和初始化所有字段之后,Spring将调用afterPropertiesSet()方法。
( Q2)在注释的第1行上,StartServiceImpl是自动生成的,并且使用"new“构造。所以这里发生了什么。容器是注入bean还是只是一个对象被实例化。
又一个奇怪的片段。Java将在创建StartServiceImpl类实例时创建AController的新实例。但是在那之后,Spring将把它自己的实例(声明为组件)分配给这个字段。而对firs实例的引用(由构造函数创建)将丢失。
( Q3)在注释的第2行中,是否调用stop,在应用上下文中调用bean上的stop,或者创建一个新对象并调用stop方法。在后一种情况下会发生什么?我们真的停止了已经启动的服务吗?我想我们不会停止这项服务
实际上服务将被停止。因为调用了service.shutdownRequested();。但是AController bean中的线程将继续工作。new AController().stop();将调用刚创建的实例的方法,但不调用控制器方法(由Spring创建的实例)。
这段代码完全错误地使用了Spring框架。
https://stackoverflow.com/questions/37717432
复制相似问题