注意:从2.8版开始,Symfony为服务配置提供了autowire:true
,从3.3版开始,Symfony提供了alias
(而不是autowire\u类型
)来将具体对象别名到接口,以便将依赖项自动注入到“控制器即服务”中。还有一个包允许控制器“动作”方法的自动接线,尽管我已经离开了这个包,并且更多地关注ADR模式的变化(基本上,这是一个带有接口方法的单个“action”类,而不是在单个类中推送一堆actions方法,最终导致架构噩梦)。这就是我多年来一直在寻找的,现在不再需要“钩住”一个像样的递归依赖注入程序(auryn)由于框架现在处理的是四年前应该有的东西,我将把这个答案留在这里,以防有人想跟踪我所做的步骤,看看内核是如何工作的,以及这个级别上的一些可用选项。
注意:虽然这个问题主要针对Symfony 3,但它也应该与Symfony 2的用户相关,因为内核逻辑似乎没有太大变化。
我想更改控制器在Symfony中的实例化方式。它们的实例化逻辑目前位于HttpKernel::handle中,更具体地说,位于HttpKernel::handleRaw中。我想用我自己的注入器代替call\u user\u func\u array($controller,$arguments)
。
到目前为止,我尝试过的选择:
HttpKernel::handle
,然后由symfony调用http_kernel:
class: AppBundle\HttpKernel
arguments: ['@event_dispatcher', '@controller_resolver', '@request_stack']
这样做的缺点是,因为handleRaw是私有的,我不能在没有黑客反射的情况下扩展它,所以我必须复制和粘贴一吨代码。
controller_resolver:
class: AppBundle\ControllerResolver
arguments: []
这是我的一个基本误解,所以我想我应该在这里记录下来。解析程序的工作是解析在何处找到作为可调用的控制器。它实际上还没有被调用。我非常满意Symfony是如何从路线中选择路线的。yml
并计算出作为可调用对象调用控制器的类和方法。
内核上添加事件侦听器。请求
kernel.request:
class: MyCustomRequestListener
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 33 /** Important, we'll get to why in a minute **/ }
看看Http内核组件文档,我们可以看到它有以下典型的目的:
要向请求中添加更多信息,请初始化部分系统,或在可能的情况下返回响应(例如,拒绝访问的安全层)。
我认为,通过创建一个新的侦听器,使用我的自定义注入器创建我的控制器,然后在该侦听器中返回一个响应,将绕过实例化控制器的其余代码。这就是我想要的!但这其中有一个主要缺陷:
Symfony Profiler没有出现或出现任何类似的东西,这只是我的回应,仅此而已。死去的我发现我可以将优先级从31切换到33,并让它在我的代码和Symfonys之间切换,我相信这是因为路由器侦听器的优先级。我觉得我走错了路。
不,这允许我改变将被call_user_func_array()
调用的可调用,而不是控制器实际上是如何实例化的,这是我的目标。
我已经把我的想法记录下来了,但我退出了。如何实现以下目标?
call\u user\u func\u array()
我为什么要这样做?
控制器在不同的情况下可以有许多不同的方法,每个方法都应该能够键入它各自需要的内容,而不是让构造函数获取所有内容,其中一些内容甚至可能不被使用,具体取决于正在执行的控制器方法。控制器并不真正遵守单一责任原则,它们是“对象边缘案例”。但事实就是这样。
我想用我自己的递归自动连接注入器来替换控制器的创建方式,以及它们的执行方式,同样是通过我的注入器进行递归自省,因为默认的Symfony包似乎没有这个功能。即使使用Symfony 2.8中最新的“autowire”服务选项。
Listener解决您的需求为时已晚,因为它排除了依赖项注入容器,这对于创建有效对象(~=服务)至关重要。
您可能正在寻找控制器自动布线功能。
如果是这样,您可能会在这个捆绑包中找到解决方案或至少灵感:http://www.tomasvotruba.cz/blog/2016/03/10/autowired-controllers-as-services-for-lazy-people/
它在以下几点满足您的需求:
为什么不从自定义的ControlllerResolverInterface
返回自己的可调用,它将以您想要的方式实例化Controller
并调用它?
它基本上是一个装饰师。
您可以使用自己的instanceController()
方法实现来扩展Symfony\Component\HttpKernel\Controller\ControllerResolver
,也可以从头开始实现ControllerResolverInterface
。
UPD:
当Symfony进行调用\u user\u func\u数组($controller,$arguments)时
在handleRaw()
中调用,$controller
变量是您从自定义ControllerResolver
返回的变量。这意味着您可以从解析器返回任何可调用的内容(可以是[$this,“callController”]
f.e.),在该可调用内容中,您可以使用Auryn创建一个新的控制器并调用它。
UPD2:
如果你还在纠结这个问题,我会添加一个例子,因为你可能会错过我在这里的意思。
use Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver;
class AutowiringControllerResolver extends ControllerResolver
{
// ... constructor stuff; assume $injector is a part of this class
protected function createController($controller)
{
$controller = parent::createController($controller);
return function (...$arguments) use ($controller) {
// you can do with resolved $arguments whatever you want
// or you can override getArguments() method and return
// empty array to discard getArguments() functionality completely
return $this->injector->execute($controller);
};
}
protected function instantiateController($classname)
{
return $this->injector->make($classname);
}
}
控制器解析器实际上做两件事。首先是获取控制器。第二种方法是获取给定操作的参数列表。
$arguments = $this->resolver->getArguments($request, $controller);
$response = call_user_func_array($controller, $arguments);
您可以重写getArguments方法来实现特殊的“action method injection”功能。您只需要确定action方法需要哪些参数并返回它们的数组。
基于另一个问题,我还认为您可能误解了autowire的功能。Autowire实际上只适用于构造函数注入。这对动作方法注入没有帮助。
如果getArguments不能解决您的需求,那么重写handle方法实际上是您唯一的选择。是的,有相当多的代码要从handleRaw复制/粘贴,但这是因为其中有相当多的工作要做。即使handleRaw受到保护,您仍然需要复制/粘贴代码,以获得要替换的一行代码。
我有一个Apache Spark应用程序在集群模式下在YARN集群上运行(Spark在此集群上有3个节点)。 当应用程序运行时,Spark UI显示2个执行器(每个执行器在不同的节点上运行)和驱动程序在第三个节点上运行。我希望应用程序使用更多的执行器,所以我尝试添加参数--num executors to Spark submit并将其设置为6。
问题内容: 我对何时实例化控制器感到困惑。另外,嵌套状态时如何实例化控制器。我可能会感到困惑,如何将范围附加到视图和控制器,也就是说,如果每个视图都有自己的控制器和范围,或者它们共享相同的范围。 有人可以解释何时实例化控制器吗?在嵌套路由下,所有视图是否共享一个控制器和范围?当我切换状态并返回另一个控制器实例化的状态时会发生什么? 以下是我的路线(配置文件): 问题答案: 要获得更详细的答案,我们
我已经坚持了几个小时。我不知道为什么我的JavaFX控制器指向null。我在中制作了一个JavaFX GUI,将控制器类及其适当的骨架代码添加到我的项目中。但是当我在我的方法中实例化控制器时,它指向null。 使用文件夹树: 我遵循了此处和此处提及的说明,以及其他一些StackOverflow页面。我完全按照上面提到的方式复制指令,但我的控制器仍然为空。 我缺乏想法,有人知道我做错了什么吗?
本文向大家介绍IOS初始化控制器的实现方法总结,包括了IOS初始化控制器的实现方法总结的使用技巧和注意事项,需要的朋友参考一下 IOS初始化控制器的实现方法总结 一.ViewControllViewController方法 二 .ViewControllViewController 与 xib方法 如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
我尝试使用过滤器和拦截器来修改从控制器方法提交的响应,但我无法这样做,因为在执行过滤器或拦截器之前提交了响应。我知道我们还有另一种选择,但这不是我正确的地方,因为目的是根据HTTP状态修改响应。如果有人有想法,请告诉我,我如何通过Spring启动和Rest来实现
我有一些测试失败,因为这个答案为我解决了这个问题https://stackoverflow.com/a/47504698/6945345,但是破坏了我的控制器测试,因为这是因为我认为没有获取JAXB-API。我该怎么做才能最好地解决这个问题? 被赋予异常的控制器测试类: 我的pom与jaxb-api的依赖关系