Asp.Net MVC Controller: декларативный AOP с Spring.Net
Возможно ли, что Spring.Net Аспекты не работают с Asp.Net Controller?
Я хочу настроить транзакции в методах действия контроллеров, но прокси не запускается.
<object id="ControllerClassPointcut" type="Spring.Aop.Support.SdkRegularExpressionMethodPointcut, Spring.Aop">
<property name="patterns">
<list>
<value>xxx.Controllers.CompanyController.*</value>
</list>
</property>
</object>
<aop:config>
<aop:advisor pointcut-ref="ControllerClassPointcut" advice-ref="TxAdvice"/>
<!-- TxAdvice taken from ServiceContext -->
</aop:config>
<tx:advice id="TxAdvice" transaction-manager="TransactionManager">
<tx:attributes>
<tx:method name="*" propagation="Required"/>
</tx:attributes>
</tx:advice>
и метод действия CompanyController:
[HttpPost]
public virtual ActionResult Create(Guid id, CompanyonViewModel vm)
{
...
}
но я совет не вступает в силу, хотя pointcut признается. Если я возьму другой класс, а не контроллер в качестве pointcut, он работает.
для некоторых методов совет работает. Например, для установщика для хранилища. Но Sprint.Net не признает, что вызывается метод действия "Создать"
Кандидат: "xxx.Controllers.CompanyController.set_CompanyService"; шаблон это 'xxx.Controllers.CompanyController.*'; matched=True Candidate advisor [DefaultObjectFactoryPointcutAdvisor: pointcut [Spring.Aop.Support.SdkRegularExpressionMethodPointcut]; Аргумент object = 'TxAdvice'] принят для targetType [xxx.Controllers.CompanyController]
Спасибо за вашу помощь
2 ответа
У меня была похожая проблема с [Transaction]
атрибут (который работает с использованием Spring.AOP
). В моем случае я назвал [Transaction]
помечал методы внутри одного класса и был удивлен, что совет по транзакции не сработал.
Объяснение было то, что при вызове [Transaction]
помечая метод внутри класса, вы держите ссылку на реальный экземпляр вместо экземпляра с проксированием AOP, поэтому вызов не перехватывается.
Когда выполняется запрос к приложению MVC, из URL-адреса запроса выбирается контроллер (из IControllerFactory
пример). На этом контроллере Execute
вызывается метод, который в свою очередь отвечает за вызов действий. Поэтому я думаю, что методы действия всегда вызываются из контроллера. Это означает, что по определению методы действия никогда не будут перехвачены. Это объяснило бы, почему эти точки обнаружены, но не срабатывают.
если я возьму другой класс, чем контроллер, как pointcut, он работает
Это также объясняет, почему запускаются pointcut для других классов, кроме контроллеров: они, скорее всего, вызываются из контроллера, который будет содержать ссылку на прокси AOP на экземпляры других классов.
... для некоторых методов совет работает... Например для установщика для хранилища
Я предполагаю, что ваш (например) CompanyController.CustomerController
имеет свойство CustomerRepository
, установите с помощью DI. Имеет смысл, что этот pointcut срабатывает, потому что сеттер вызывается извне CompanyController.CustomerController
например, вашим DI-контейнером (или вашим ControllerFactory
).
Решением может быть введение сервисных объектов, для которых вы определяете рекомендации по транзакциям, которые вы теперь имеете на своих контроллерах. С ваших контроллеров вы вызываете методы для этих сервисных объектов - и затем запускаются pointcuts.
Можете ли вы попробовать с конфигурацией
<aop:config proxy-target-type="true">
Это создаст прокси на основе наследования. Вам может понадобиться загрузить последнюю ночную сборку spirng.net, чтобы это работало (не 1.3.0).