我在基于spring mvc的应用程序中使用Aspect进行日志记录活动.我正在使用@controller注释来定义我的应用程序中的任何控制器.我在两个不同的包中有两个不同的控制器说
我可以通过使用将方面应用于一个特定的控制器包
<aop:config>
<aop:pointcut id="pointcut1"
expression="execution(* package1.*.*(..))"
id="policy1" />
<aop:aspect ref="aspect1" order="1">
<aop:before pointcut-ref="pointcut1" method="before" arg-names="joinPoint" />
<aop:after-returning returning="returnValue" arg-names="joinPoint, returnValue" pointcut-ref="pointcut1" method="after" />
</aop:aspect>
</aop:config>
<bean id="aspect1" class="com......aspectclass" />
Run Code Online (Sandbox Code Playgroud)
我的问题是如何指定在一个以上的不同包装的表达(*包1. ..(..))**.
现在我宣布为每个包在一个方面的一个单独的一个单独的切入点aop:before,并aop:after为每个切入点条目.但我认为这应该是定义多个包切入点的理想方式.
使用AspectJ时,为什么要在@Configurable上使用@Component.
我有@Transactional支持的Spring和AspectJ设置,自我调用的方面以及注入JPA实体.这非常有效.
我正在将@Component用于大多数需要注入的类,因此要么将它们注入到它们的依赖项中.或者,当我不能,注入ApplicationContext然后使用getBean()作为最后的手段.我只为需要注入的JPA实体(Hibernate)保留@Configurable.我也开始使用@Configurable进行jUnit测试,使编写测试变得容易.这也很有效.
但我很好奇.如果AspectJ现在使用@Configurable注释自动注入(bean化)任何东西,无论它是如何构造的; getBean(),new(),@ Autowired.为什么我不能只为我的所有bean切换到使用@Configurable?然后我可以完全取消应用程序上下文和getBean(),只需要new()我无法注入的任何类.
我意识到我没有提到XML bean配置.我并不回避这一点,但这个项目并不需要任何.我只是构造函数或setter在测试时注入依赖项.很容易.
任何人都知道为什么显然不可能将AOP与带注释的MVC控制器一起使用?(见邮政).我有一个@Controller,一旦我添加切入点就会停止工作.问题不在于拦截器没有被调用,而是@Controller只是停止工作(在日志中你可以看到,而不是"映射的URL路径[/ xx]到处理器'Yyy'"你得到一个"没有URL"确定的路径").
我知道有一种通过handlerMapping向控制器添加拦截器的机制,但我的问题是特定于AOP拦截器.注释控制器只是在Spring容器中像任何其他pojo一样pojos吗?有什么不同?为什么?
@Controller
@RequestMapping("/user")
public class RestTestImpl implements RestTest {
@RequestMapping(value="/", method={RequestMethod.GET})
public @ResponseBody String deleteUsers(String arg) {
return "Xxxxx";
}
}
Run Code Online (Sandbox Code Playgroud)
在我的servlet-Context中我有:
<context:component-scan base-package="org.xxx.yyy"></context:component-scan>
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
. . .
</bean>
Run Code Online (Sandbox Code Playgroud)
一切都很好.
但是当我添加:
<aop:config>
<aop:pointcut expression="execution(* org.xxx.*(..))" id="pc1"/>
<aop:advisor advice-ref="hibernateInterceptor" pointcut-ref="pc1" order="2" />
</aop:config>
Run Code Online (Sandbox Code Playgroud)
控制器停止作为控制器(没有错误,只是它停止绑定到指定的URL)!
我是AOP的新手.我有这样的问题.
package org.suman.Aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class LoginAspect {
//@Before("execution(public String getName())")
//@Before("execution(public String org.suman.Model.Triangle.getName())")
//@Before("execution(* get*())")
//@Before("execution(* get*(..))")
//@Before("execution(* org.suman.Model.*.get*())")
//@Before("execution(* get*())&& within(org.suman.Model.Circle)")
@Before("execution(* get*())&& allCircle()")
//@Before("allGetters() && allCircle()")
public void LoginAdvice()
{
System.out.println("Advice run.. getMethod is called");
}
@Before("execution(* get*())")
//@Before("allGetters()")
public void SecondAdvice()
{
System.out.println("this is a second Advice");
}
@Pointcut("execution(* get*())")
public void allGetters(){}
//@Pointcut("execution (* * org.suman.Model.Circle.*(..))")
@Pointcut("within(org.suman.Model.Circle)")
public void allCircle(){}
}
Run Code Online (Sandbox Code Playgroud)
当使用切入点时,方法allGetters()为LoginAdvice方法,如果我使用@Before("execution(*get*())"然后没有错误但是如果我使用@Before("allGetters()")则会给出错误" java.lang.IllegalArgumentException::: 0处的错误找不到引用的切入点allGetters
如果我使用@Before("execution(*get*())&&(org.suman.Model.Circle)")而不是方法名称,它可以工作.
我的xml是这样的:
<?xml version="1.0" encoding="UTF-8" …Run Code Online (Sandbox Code Playgroud) 原始问题的概要:使用带有AOP代理的标准Spring事务,不可能从同一类中的非@Transactional-marked方法调用@ Transactional-marked方法并且在事务内(特别是由于前面提到的)代理).据说在AspectJ模式下使用Spring Transactions可以实现这一点,但它是如何完成的?
编辑:使用加载时编织的AspectJ模式中Spring事务的完整纲要:
将以下内容添加到META-INF/spring/applicationContext.xml:
<tx:annotation-driven mode="aspectj" />
<context:load-time-weaver />
Run Code Online (Sandbox Code Playgroud)
(我假设您已经在应用程序上下文中设置了一个AnnotationSessionFactoryBean和一个HibernateTransactionManager设置.您可以将标签添加transaction-manager="transactionManager"为属性<tx:annotation-driven />,但如果事务管理器bean的id属性值实际上是" transactionManager",则它是多余的,因为" transactionManager"是该属性的默认值.)
添加META-INF/aop.xml.内容如下:
<aspectj>
<aspects>
<aspect name="org.springframework.transaction.aspectj.AnnotationTransactionAspect" />
</aspects>
<weaver>
<include within="my.package..*" /><!--Whatever your package space is.-->
</weaver>
</aspectj>
Run Code Online (Sandbox Code Playgroud)
添加aspectjweaver-1.7.0.jar和spring-aspects-3.1.2.RELEASE.jar你的classpath.我使用Maven作为我的构建工具,所以这里是<dependency />项目POM.xml文件的声明:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
spring-instrument-3.1.2.RELEASE.jar不需要作为<dependency />你的classpath,但你仍然需要它在 …
我想将我的项目升级到spring 4,但是,我得到了aspectweaver-1.8.0.M1.jar的缺失依赖项.当我看一下依赖层次结构时,我发现spring-aspects-4.0.0需要这个文件,它在自己的pom.xml中有以下内容:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.0.M1</version>
<scope>compile</scope>
</dependency>
Run Code Online (Sandbox Code Playgroud)
检查maven存储库后,我无法找到此工件,因为最新的aspectweaver稳定版本是1.7.4.
现在我无法理解两件事:
由于此依赖项的范围是编译,为什么我的应用程序需要它?我不想编译spring-aspects.jar !!
为什么弹簧方面-4.0.0.jar(这是稳定的)使用非稳定组件的版本?这不会使spring-aspects-4.0.0也不稳定吗?
谢谢
我从未使用Spring AOP并尝试配置我的第一个bean.我似乎正确配置它,但我得到一个例外,找不到bean.
我的方面是 -
@Aspect
@Component
public class IdentificationAspect {
@Before("execution(* ru.sbt.filial.cards.aspect.SomeBean.*(..))")
public void logBefore(JoinPoint joinPoint) throws Throwable {
System.out.println("logBefore() is running!");
System.out.println("hijacked : " + joinPoint.getSignature().getName());
System.out.println("******");
}
}
Run Code Online (Sandbox Code Playgroud)
AOP找不到我的豆子是 -
package ru.sbt.filial.cards.aspect;
import org.springframework.stereotype.Component;
@Component
public class SomeBean {
public void printSmth() {
System.out.println("!!!!!!!!!!!");
}
}
Run Code Online (Sandbox Code Playgroud)
我有以下例外 -
Caused by: java.lang.IllegalArgumentException: warning no match for this type name: ru.sbt.filial.cards.aspect.SomeBean [Xlint:invalidAbsoluteTypeName]
at org.aspectj.weaver.tools.PointcutParser.parsePointcutExpression(PointcutParser.java:301)
at org.springframework.aop.aspectj.AspectJExpressionPointcut.buildPointcutExpression(AspectJExpressionPointcut.java:207)
at org.springframework.aop.aspectj.AspectJExpressionPointcut.getFallbackPointcutExpression(AspectJExpressionPointcut.java:358)
at org.springframework.aop.aspectj.AspectJExpressionPointcut.matches(AspectJExpressionPointcut.java:255)
at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:208)
at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:262)
at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:294)
at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:117)
at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:87) …Run Code Online (Sandbox Code Playgroud) 我需要使用@X注释的类中的方法或使用@X注释的方法的切入点.我还需要注释对象.如果类和方法都被注释,我更喜欢将方法注释作为参数.
我尝试了以下操作,这会产生"不一致的绑定"警告.(为什么不将它们设置为null?)
@Around("@annotation(methodLevelX) || @within(classLevelX)")
public Object advise(ProceedingJoinPoint pjp, X methodLevelX, X classLevelX)
Run Code Online (Sandbox Code Playgroud)
以下内容创建了"跨越'||'的参数x的模糊绑定 在切入点"警告.(在我看来,这不一定有意义:为什么不绑定第一个短路评估?)
@Around("@annotation(x) || @within(x)")
public Object advise(ProceedingJoinPoint pjp, X x)
Run Code Online (Sandbox Code Playgroud)
如果存在类和方法注释,则将先前的尝试拆分为两个自然会导致两个方法调用.
我知道我可以通过这样的切入点获得带有反射和我想要的注释的方法和类:
@Around("@annotation(com.package.X) || @within(com.package.X)")
Run Code Online (Sandbox Code Playgroud)
但我不愿意.
有没有"一个切入点,一个方法,一个注释参数",我的要求的解决方案不需要反思?
对于文件上传,我试图在我的Spring Controller中注入并使用Validator,如下所示:
@RestController
@RequestMapping("/api")
public class FileController{
@Autowired
private MessageSource messageSource;
@Autowired
FileValidator validator;
@InitBinder("file")
public void initBinderFile(WebDataBinder binder) {
binder.setValidator(validator);
}
@RequestMapping(value = "/fileUpload2", method = RequestMethod.POST, produces = {"text/plain"})
@PreAuthorize("hasAuthority('ADMINISTRATOR')")
public String singleFileUpload2(@Valid @ModelAttribute("file") File file, BindingResult result) throws IOException {
if (result.hasErrors()) {
String errorString = "";
for (ObjectError error : result.getAllErrors()) {
errorString = errorString.concat(messageSource.getMessage(error.getCode(), new String[]{}, Locale.ENGLISH)+"\n");
}
return errorString;
} else {
MultipartFile multipartFile = file.getFile();
String fileName = multipartFile.getOriginalFilename();
System.out.println("Fetching file: "+fileName);
return …Run Code Online (Sandbox Code Playgroud) 我创建了一个包含@Transactional注释的Aspect.我的建议正在按预期调用,但新实体AuditRecord永远不会保存到数据库中,看起来我的@Transactional注释不起作用.
@Aspect
@Order(100)
public class ServiceAuditTrail {
private AppService appService;
private FooRecordRepository fooRecordRepository;
@AfterReturning("execution(* *.app.services.*.*(..))")
public void logAuditTrail(JoinPoint jp){
Object[] signatureArgs = jp.getArgs();
String methodName = jp.getSignature().getName();
List<String> args = new ArrayList<String>();
for(Object arg : signatureArgs){
args.add(arg.toString());
}
createRecord(methodName, args);
}
@Transactional
private void createRecord(String methodName, List<String> args){
AuditRecord auditRecord = new AuditRecord();
auditRecord.setDate(new Date());
auditRecord.setAction(methodName);
auditRecord.setDetails(StringUtils.join(args, ";"));
auditRecord.setUser(appService.getUser());
fooRecordRepository.addAuditRecord(auditRecord);
}
public void setAppService(AppService appService) {
this.appService = appService;
}
public void setFooRecordRepository(FooRecordRepository fooRecordRepository) {
this.fooRecordRepository= fooRecordRepository;
}
}
Run Code Online (Sandbox Code Playgroud)
bean上下文如下: …
spring-aop ×10
java ×7
spring ×7
aop ×4
spring-mvc ×2
annotations ×1
aspect ×1
configurable ×1
controller ×1
hibernate ×1
maven ×1
pointcut ×1
spring-boot ×1
transactions ×1