我创建了一个Spring网站。 我使用了一个抽象的通用控制器类,具有不同的实现。 如果我不在任何控制器上激活Aspect类,它的效果很好。
如果我激活一个Aspect,那么所有Mappings似乎都被停用了:
DEBUG:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - 找不到[/ contact / 2]的处理程序方法
警告:org.springframework.web.servlet.PageNotFound - 在DispatcherServlet中找不到带有URI [/ clubhelperbackend / contact / 2]的HTTP请求的映射,名称为' appServlet'
这是我的抽象控制器:
public abstract class AbstractController<T extends Data> implements ClubController<T> {
protected Dao<T> dao;
private Class<T> elementClass;
public AbstractController(Dao<T> dao, Class<T> element) {
super();
this.dao = dao;
this.elementClass = element;
}
@Override
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public String getAsView(@PathVariable("id") long id, @RequestParam(required = false) boolean ajax, Model m) {
String mapping = elementClass.getSimpleName();
m.addAttribute(mapping, getById(id));
return mapping + "Get" + (ajax ? "Ajax" : "");
}
@Override
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE, produces = "application/json")
public T delete(@PathVariable("id") long id) {
T obj = getById(id);
// dao.delete(id);
return obj;
}
}
实施:
@Controller
@RequestMapping("/contact")
public class ContactController extends AbstractController<Contact> {
@Autowired
public ContactController(Dao<Contact> contactDao) {
super(contactDao, Contact.class);
}
}
这是我的看点:
@Aspect
@Component
public class DeletedStorageAspect {
//
// private DeletedEntriesDao deletedEntriesDao;
//
// @Autowired
// public DeletedStorageAspect(DeletedEntriesDao deletedEntriesDao) {
// super();
// this.deletedEntriesDao = deletedEntriesDao;
// }
@Pointcut("execution (public * de.kreth.clubhelperbackend.controller.abstr.AbstractController.delete(..))")
private void invocation() {
}
@AfterReturning(pointcut = "invocation()", returning = "deleted")
public void storeDeleted(JoinPoint joinPoint, Data deleted) {
System.out.println("Deleted: " + deleted);
String tableName = deleted.getClass().getSimpleName();
long id = deleted.getId();
Date now = new Date();
DeletedEntries entry = new DeletedEntries(-1L, tableName, id, now, now);
System.out.println(entry);
// deletedEntriesDao.insert(entry);
}
}
这是我的beans.xml的一部分:
<aop:aspectj-autoproxy>
<aop:include name="mysqlDbCheckAspect" />
<aop:include name="daoLoggerAspect" />
<aop:include name="controllerSecurityAspect" />
<aop:include name="deletedStorageAspect" />
</aop:aspectj-autoproxy>
我可以通过评论deletedStorageAspect来恢复全部功能。
导致这种行为的原因是什么?为什么映射没有被识别出来?控制器上不允许使用方面吗?
希望得到一些帮助。
答案 0 :(得分:4)
默认情况下,当Spring使用AOP时,spring会创建代理。根据您在类(或不是)上实现接口的事实,它将创建JDK动态代理(基于接口)或基于CGLIB的代理(基于类)。
public abstract class AbstractController<T extends Data> implements ClubController<T> {
对于基于接口的代理(适用于您),MVC基础架构不再能够看到@RequestMapping
注释,也不会再检测到您的映射。在您实现接口时,这也适用于您。有关使用请求映射进行代理的问题,请参阅the reference guide。
要修复它,您必须强制使用基于类的代理,为此proxy-target-class="true"
添加<aop:aspectj-auto-proxy />
。
<aop:aspectj-autoproxy proxy-target-class="true">
答案 1 :(得分:0)
我不是AOP专家。但是通过查看你的代码我可以说抽象类没有执行,这可能是根本原因。所以必须修改Pointcut执行表达式。
如果您没有对子类使用删除签名,您可以轻松地像抽象表达式一样移动到bello。它只是在包装之内说的。
@Pointcut("execution (public * de.kreth.clubhelperbackend.controller.*.*.delete(..))")
private void invocation() {
}
您可以像这样使用逻辑门进行表达
@Pointcut("target(de.kreth.clubhelperbackend.controller.abstr.AbstractController)")
private void anyAbstractOperation() {}
@Pointcut("execution(public * *.delete(..))")
private void anyDeleteOperation() {}
@Pointcut("anyAbstractOperation() && anyDeleteOperation()")
private void invocation() {}
参考:
1。http://docs.spring.io/spring/docs/2.5.x/reference/aop.html#aop-pointcuts-combining
2。http://www.baeldung.com/spring-aop-pointcut-tutorial
3。http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-using-aspectj
说明关于此目标
此限制匹配连接点,其中bean引用是给定类型的实例,而目标限制匹配连接点,其中目标对象是实例的给定的类型。前者在Spring AOP创建基于CGLIB的代理时起作用,后者在创建基于JDK的代理时使用。假设目标类实现了一个接口:
public class FooDao implements BarDao {
...
}
在这种情况下,Spring AOP将使用基于JDK的代理,您应该使用目标PCD,因为代理对象将是Proxy类的实例并实现BarDao接口:
@Pointcut("target(org.baeldung.dao.BarDao)")
另一方面,如果FooDao没有实现任何接口或者proxyTargetClass属性设置为true,则代理对象将是FooDao的子类,并且可以使用此PCD:
@Pointcut("this(org.baeldung.dao.FooDao)")