我过去曾使用过Spring。我搬到了另一个团队,在那里我熟悉了代码库。我找到了以下代码,并试图了解它是如何工作的以及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。这非常有用。但它没有回答我的问题。
答案 0 :(得分:2)
此代码在许多层面都存在缺陷。
我一直保持线程运行scheduling the task with the @Scheduled
annotation并使用控制器来切换一个标志,该标志决定线程是否实际执行某些操作,例如。
( /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/)
现在所有其他控制器都会切换&#34;活动&#34;的值。领域。优点:
答案 1 :(得分:1)
我会特意回答这些问题,因为代码的目的很难理解(至少对我来说)。
Q1)我不清楚这段代码试图实现的目标。正如你所注意到的那样,它不是一个控制器,我怀疑它以这种方式注册的唯一原因是它被自动扫描(这也可以通过使用@Controller
来完成。这只是一个预感,我不太了解它的目的。
Q2)答案是将创建两个实例,一个通过new
,另一个作为bean。在Spring中运行时,字段的最终值是bean,因为依赖注入在构造之后发生。通常,这是在设想在Spring外部使用类(例如单元测试)时完成的,以便可以使用默认值初始化该字段。
Q3)stop()
将在新实例上调用,而不是bean。服务bean因为在注入bean的那一行上面的直接调用而停止了,但是我想,下一个将是NPE,因为afterPropertiesSet
没有在通过new
创建的目标对象上调用。这不能在日志中显示NPE的唯一原因是因为下面的例外被吞下。 thread
变量未初始化并保持为NULL。
希望这有帮助,
答案 2 :(得分:1)
您发布的代码非常奇怪。
Q1)localhost:8080 / project / start应该做什么。那里 是没有定义的GET或POST方法。
我认为localhost:8080/project/start
将返回404错误(请求的资源不可用)。因为AController
中没有映射方法。类级别上的@RequestMapping
注释不足以向控制器发出请求。必须有映射方法。
但无论如何都会开始服务。因为AController
实现了InitializingBean
。在创建控制器并初始化所有字段后,Spring将调用方法afterPropertiesSet()
。
Q2)在注释行1上,StartServiceImpl是自动装配的 用&#34; new&#34;构建。那么这里发生了什么。做容器 注入bean或只是一个对象被实例化。
另一个奇怪的片段。 Java将在创建StartServiceImpl
类的实例时创建AController
的新实例。但在那之后,Spring会将它自己的实例(声明为组件)分配给该字段。并且对firs实例的引用(由构造函数创建)将丢失。
Q3)再次在注释第2行中,调用stop,调用stop 应用程序上下文中的bean或新对象被创建 调用stop方法。在后一种情况下会发生什么?是 我们真的停止了已启动的服务吗?我想我们是 不停止服务
实际上服务将被停止。因为service.shutdownRequested();
的调用。但是AController
bean中的线程将继续工作。 new AController().stop();
将调用刚刚创建的实例的方法,但不调用控制器的方法(由Spring创建的实例)。
这段代码完全错误地使用了Spring框架。