有没有一种方法可以在使用 spring AOP 执行某行代码后调用建议方法
Is there a way of calling an advice method after execution of certain line of code using spring AOP
为了日志目的,我一直在写 Aspect。现在我可以使用之前和之后的建议了。但是是否可以在执行某些业务逻辑后调用建议。这是我当前的代码,我想用建议替换我的代码。怎么做?
@ComponentScan
@EnableCaching
@EnableAutoConfiguration(exclude = {MetricFilterAutoConfiguration.class, MetricRepositoryAutoConfiguration.class})
public class Application {
private final Logger log = LoggerFactory.getLogger(Application.class);
@Inject
private Environment env;
@Inject
private AppConfig appConfig;
public void myBusinessLogicMethod(){
if (myVariable == 0) {
log.info("No Spring profile configured, running with default configuration");
//rest of the business logic here
} else {
log.info("Running with number profile(s) : {}",myVariable);
// //rest of the business logic here
}
我的看点class
@Aspect
@Order(0)
public class LoggingAspect {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Inject
private HttpServletRequest request;
@Inject
private HttpServletResponse response;
@Inject
private Environment env;
@Pointcut("(within(com.repository.*) || within(com.service.*) || "
+ "within(com.web.rest.*)) && "
+ "!@annotation(com.aop.logging.NoLogging)")
public void loggingPoincut() {
}
@Before("within(com.web.rest.*) && "
+ "!@annotation(com.aop.logging.NoLogging)")
public void beforeRest(JoinPoint point) throws UnknownHostException {
String ipAddress = getIpAddress();
if (log.isDebugEnabled()) {
log.debug(">>>>>> From IP {}", isIpAvailble(ipAddress));
log.debug("Enter: {}.{}() with argument[s] = {}", point.getSignature().getDeclaringTypeName(),
point.getSignature().getName(), Arrays.toString(point.getArgs()));
}
}
@After("within(com.web.rest.*) && "
+ "!@annotation(com.aop.logging.NoLogging)")
public void afterRest(JoinPoint point) throws UnknownHostException {
if (log.isDebugEnabled()) {
log.debug("Exit: {}.{}()", point.getSignature().getDeclaringTypeName(), point.getSignature()
.getName());
log.debug("<<<<<< Rest Call Finished {} ", response.getStatus());
}
}
}
如何用我方面的建议替换紧密耦合的日志 class。
简单的答案是:使用 Spring AOP,您可以拦截方法调用,而不是单行代码。即使可以,这也将是一场维护噩梦,因为方法中的代码经常更改。即使您有稳定的 API 个 public 方法,它们也是黑盒子,您(或您的一位同事)可以随时更改它们的内部实现。
但解决方案很简单:应用“清洁代码”原则(我希望你已经读过这本书或已经从其他来源了解软件工艺运动),即使用简短的方法,将更复杂的代码分解成更小的代码,可重用,命名良好且可维护的部件,复杂性低。将方法分解到日志记录所需的粒度级别,例如
public void myBusinessLogicMethod() {
if (myVariable == 0)
smallerBusinessLogicA(myVariable, someParameter);
else
smallerBusinessLogicB(myVariable);
}
然后使用您的日志切入点定位那些分解出的方法并记录它们的名称、参数 and/or 结果(无论您需要什么)。为了使其与 Spring AOP 一起使用,您需要注意
- 将辅助方法分解为其他 Spring 组件 classes 因为 Spring AOP 不支持自调用拦截
- 或者自我注入 bean,这样你就可以使用注入的 bean 调用辅助方法(即你使用 AOP 代理而不是真正的实现 class 下面对 AOP 一无所知)
- 或从 Spring AOP 切换到完整的 AspectJ,它不使用代理并使用自调用。
SpringAOP和AspectJ的另一个区别是前者只能针对非私有方法,而AspectJ没有这种限制。
为了日志目的,我一直在写 Aspect。现在我可以使用之前和之后的建议了。但是是否可以在执行某些业务逻辑后调用建议。这是我当前的代码,我想用建议替换我的代码。怎么做?
@ComponentScan
@EnableCaching
@EnableAutoConfiguration(exclude = {MetricFilterAutoConfiguration.class, MetricRepositoryAutoConfiguration.class})
public class Application {
private final Logger log = LoggerFactory.getLogger(Application.class);
@Inject
private Environment env;
@Inject
private AppConfig appConfig;
public void myBusinessLogicMethod(){
if (myVariable == 0) {
log.info("No Spring profile configured, running with default configuration");
//rest of the business logic here
} else {
log.info("Running with number profile(s) : {}",myVariable);
// //rest of the business logic here
}
我的看点class
@Aspect
@Order(0)
public class LoggingAspect {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Inject
private HttpServletRequest request;
@Inject
private HttpServletResponse response;
@Inject
private Environment env;
@Pointcut("(within(com.repository.*) || within(com.service.*) || "
+ "within(com.web.rest.*)) && "
+ "!@annotation(com.aop.logging.NoLogging)")
public void loggingPoincut() {
}
@Before("within(com.web.rest.*) && "
+ "!@annotation(com.aop.logging.NoLogging)")
public void beforeRest(JoinPoint point) throws UnknownHostException {
String ipAddress = getIpAddress();
if (log.isDebugEnabled()) {
log.debug(">>>>>> From IP {}", isIpAvailble(ipAddress));
log.debug("Enter: {}.{}() with argument[s] = {}", point.getSignature().getDeclaringTypeName(),
point.getSignature().getName(), Arrays.toString(point.getArgs()));
}
}
@After("within(com.web.rest.*) && "
+ "!@annotation(com.aop.logging.NoLogging)")
public void afterRest(JoinPoint point) throws UnknownHostException {
if (log.isDebugEnabled()) {
log.debug("Exit: {}.{}()", point.getSignature().getDeclaringTypeName(), point.getSignature()
.getName());
log.debug("<<<<<< Rest Call Finished {} ", response.getStatus());
}
}
}
如何用我方面的建议替换紧密耦合的日志 class。
简单的答案是:使用 Spring AOP,您可以拦截方法调用,而不是单行代码。即使可以,这也将是一场维护噩梦,因为方法中的代码经常更改。即使您有稳定的 API 个 public 方法,它们也是黑盒子,您(或您的一位同事)可以随时更改它们的内部实现。
但解决方案很简单:应用“清洁代码”原则(我希望你已经读过这本书或已经从其他来源了解软件工艺运动),即使用简短的方法,将更复杂的代码分解成更小的代码,可重用,命名良好且可维护的部件,复杂性低。将方法分解到日志记录所需的粒度级别,例如
public void myBusinessLogicMethod() {
if (myVariable == 0)
smallerBusinessLogicA(myVariable, someParameter);
else
smallerBusinessLogicB(myVariable);
}
然后使用您的日志切入点定位那些分解出的方法并记录它们的名称、参数 and/or 结果(无论您需要什么)。为了使其与 Spring AOP 一起使用,您需要注意
- 将辅助方法分解为其他 Spring 组件 classes 因为 Spring AOP 不支持自调用拦截
- 或者自我注入 bean,这样你就可以使用注入的 bean 调用辅助方法(即你使用 AOP 代理而不是真正的实现 class 下面对 AOP 一无所知)
- 或从 Spring AOP 切换到完整的 AspectJ,它不使用代理并使用自调用。
SpringAOP和AspectJ的另一个区别是前者只能针对非私有方法,而AspectJ没有这种限制。