Skip to content

Commit

Permalink
✨ Enhancement for LoggerContextHolder
Browse files Browse the repository at this point in the history
  • Loading branch information
lzhpo committed Apr 21, 2024
1 parent 74360a4 commit 8b228ea
Show file tree
Hide file tree
Showing 16 changed files with 195 additions and 447 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ public class LoggerEventListener {
- success: 业务方法是否执行成功。
- errors: 业务方法执行期间发生的异常。

#### 2.4 关于`@Logger`注解在IDEA设置SpringEL的提示
#### 2.4 异步监听日志事件

#### 2.5 关于`@Logger`注解在IDEA设置SpringEL的提示

`@Logger` 注解中的属性已经支持在 IDEA 中自动有 SpringEL 的提示,无需手动设置。

Expand Down
4 changes: 3 additions & 1 deletion src/main/java/com/lzhpo/logger/LoggerAspect.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ private void resolveLogger(ProceedingJoinPoint joinPoint, Logger logger, LoggerE

LoggerExpressionEvaluator evaluator = new LoggerExpressionEvaluator();
ParameterNameDiscoverer discoverer = evaluator.getParameterNameDiscoverer();
LoggerEvaluationContext context = LoggerContextHolder.getContext(object, method, event.getResult(), args, discoverer);
LoggerElementKey elementKey = new LoggerElementKey(object, method, event.getResult(), args, discoverer);

LoggerEvaluationContext context = LoggerContextHolder.getContext(elementKey);
if (!Boolean.parseBoolean(evalExpression(logger.condition(), event, context, evaluator))) {
log.debug("The resolved condition is false in @Logger.");
return;
Expand Down
76 changes: 49 additions & 27 deletions src/main/java/com/lzhpo/logger/LoggerContextHolder.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,44 +15,51 @@
*/
package com.lzhpo.logger;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.ttl.TransmittableThreadLocal;
import java.lang.reflect.Method;
import java.util.Optional;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.Assert;

/**
* @author lzhpo
*/
// spotless:off
@Slf4j
@UtilityClass
public class LoggerContextHolder {

private static final TransmittableThreadLocal<LoggerEvaluationContext> EVALUATION_CONTEXT = new TransmittableThreadLocal<>();
private static final TransmittableThreadLocal<LoggerEvaluationContext> EVALUATION_CONTEXT =
new TransmittableThreadLocal<>();

/**
* Get {@link #EVALUATION_CONTEXT}.
*
* @param rootObject the root object
* @param method the method
* @param result the result
* @param args the arguments
* @param discoverer the parameter name discoverer
* @param elementKey the logger element key
* @return {@link LoggerEvaluationContext}
*/
public static LoggerEvaluationContext getContext(Object rootObject, Method method, Object result, Object[] args, ParameterNameDiscoverer discoverer) {
return Optional.ofNullable(EVALUATION_CONTEXT.get()).orElseGet(() -> {
LoggerEvaluationContext context = new LoggerEvaluationContext(rootObject, method, args, discoverer);
context.setVariable(LoggerConstant.VARIABLE_RESULT, result);
LoggerFunctionRegistrar.registerFunction(context);
EVALUATION_CONTEXT.set(context);
log.debug("The evaluation context is null, created new context, current thread name: {}", Thread.currentThread().getName());
return context;
});
public static LoggerEvaluationContext getContext(LoggerElementKey elementKey) {
return Optional.ofNullable(EVALUATION_CONTEXT.get())
.map(context -> {
initializeIfNecessary(elementKey, context);
return context;
})
.orElseGet(() -> {
LoggerEvaluationContext context = new LoggerEvaluationContext();
initializeIfNecessary(elementKey, context);
EVALUATION_CONTEXT.set(context);
log.debug(
"[{}] Created new context.", Thread.currentThread().getName());
return context;
});
}

/**
* Get {@link #EVALUATION_CONTEXT}.
*
* @return {@link LoggerEvaluationContext}
*/
public static LoggerEvaluationContext getContext() {
return Optional.ofNullable(EVALUATION_CONTEXT.get()).orElseGet(LoggerEvaluationContext::new);
}

/**
Expand All @@ -62,9 +69,9 @@ public static LoggerEvaluationContext getContext(Object rootObject, Method metho
* @param value the variable value
*/
public static void putVariable(String name, Object value) {
StandardEvaluationContext context = EVALUATION_CONTEXT.get();
Assert.notNull(context, "The evaluation context is null");
LoggerEvaluationContext context = getContext();
context.setVariable(name, value);
EVALUATION_CONTEXT.set(context);
}

/**
Expand All @@ -74,17 +81,32 @@ public static void putVariable(String name, Object value) {
* @return the variable value
*/
public static Object lookupVariable(String name) {
StandardEvaluationContext context = EVALUATION_CONTEXT.get();
Assert.notNull(context, "The evaluation context is null");
return context.lookupVariable(name);
return getContext().lookupVariable(name);
}

/**
* Clear {@link #EVALUATION_CONTEXT}.
*/
public static void clearContext() {
EVALUATION_CONTEXT.remove();
log.debug("Cleared evaluation context, current thread name: {}", Thread.currentThread().getName());
log.debug("[{}] Cleared evaluation context.", Thread.currentThread().getName());
}

/**
* Initialize context's fields if it has empty.
*
* @param elementKey {@link LoggerElementKey}
* @param context {@link LoggerEvaluationContext}
*/
private static void initializeIfNecessary(LoggerElementKey elementKey, LoggerEvaluationContext context) {
if (ObjectUtil.hasEmpty(context.getMethod(), context.getMethod(), context.getDiscoverer())) {
context.setRootObject(elementKey.getRootObject());
context.setMethod(elementKey.getMethod());
context.setArguments(elementKey.getArguments());
context.setDiscoverer(elementKey.getDiscoverer());
context.setVariable(LoggerConstant.VARIABLE_RESULT, elementKey.getResult());
LoggerFunctionRegistrar.registerFunction(context);
log.debug("The context has null fields, already initialized.");
}
}
}
// spotless:on
45 changes: 45 additions & 0 deletions src/main/java/com/lzhpo/logger/LoggerElementKey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright lzhpo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lzhpo.logger;

import java.lang.reflect.Method;
import java.util.Optional;
import lombok.Getter;
import org.springframework.core.ParameterNameDiscoverer;

/**
* @author lzhpo
*/
@Getter
public class LoggerElementKey {

private final Object rootObject;
private final Method method;
private final Object result;
private final Object[] arguments;
private final ParameterNameDiscoverer discoverer;

public LoggerElementKey(
Object rootObject, Method method, Object result, Object[] arguments, ParameterNameDiscoverer discoverer) {
this.arguments = arguments;
this.result = result;
this.rootObject =
Optional.ofNullable(rootObject).orElseThrow(() -> new IllegalArgumentException("rootObject is null"));
this.method = Optional.ofNullable(method).orElseThrow(() -> new IllegalArgumentException("method is null"));
this.discoverer =
Optional.ofNullable(discoverer).orElseThrow(() -> new IllegalArgumentException("discoverer is null"));
}
}
28 changes: 19 additions & 9 deletions src/main/java/com/lzhpo/logger/LoggerEvaluationContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.lang.reflect.Method;
import java.util.Arrays;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.spel.support.StandardEvaluationContext;
Expand All @@ -41,17 +42,26 @@
@Getter
public class LoggerEvaluationContext extends StandardEvaluationContext {

private final Method method;
private final Object[] arguments;
private final ParameterNameDiscoverer discoverer;
@Setter
private Method method;

@Setter
private Object[] arguments;

@Setter
private ParameterNameDiscoverer discoverer;

private boolean argumentsLoaded = false;

public LoggerEvaluationContext(
Object rootObject, Method method, Object[] arguments, ParameterNameDiscoverer discoverer) {
super(rootObject);
this.method = method;
this.arguments = arguments;
this.discoverer = discoverer;
public LoggerEvaluationContext() {
// NOP
}

public LoggerEvaluationContext(LoggerElementKey loggerElementKey) {
super(loggerElementKey.getRootObject());
this.method = loggerElementKey.getMethod();
this.arguments = loggerElementKey.getArguments();
this.discoverer = loggerElementKey.getDiscoverer();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lzhpo.logger.service;
package com.lzhpo.logger;

import com.lzhpo.logger.domain.CreateOrderRequest;
import com.lzhpo.logger.domain.CreateOrderResponse;
import com.lzhpo.logger.domain.ModifyOrderRequest;
import com.lzhpo.logger.domain.ModifyOrderResponse;
import org.springframework.boot.test.context.TestComponent;
import org.springframework.web.bind.annotation.RequestParam;

/**
* @author lzhpo
*/
public interface OrderService {
@TestComponent
public class LoggerAction {

CreateOrderResponse createOrder(CreateOrderRequest request);
@Logger(message = "'将地址从' + #oldAddress + '修改为' + #newAddress")
public void updateAddress(@RequestParam String oldAddress, @RequestParam String newAddress) {}

ModifyOrderResponse modifyOrder(ModifyOrderRequest request);
@Logger(message = "'将地址从' + #oldAddress + '修改为' + #newAddress")
public void updateNewAddress(@RequestParam String newAddress) {
LoggerContextHolder.putVariable("oldAddress", "光明小区1号");
}
}
46 changes: 46 additions & 0 deletions src/test/java/com/lzhpo/logger/LoggerActionTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright lzhpo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lzhpo.logger;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;

/**
* @author lzhpo
*/
@Slf4j
@EnableAspectJAutoProxy(proxyTargetClass = true)
@SpringBootTest(classes = LoggerTestApplication.class)
@Import({LoggerAutoConfiguration.class, LoggerAction.class, LoggerListenerTest.class})
class LoggerActionTest {

@Autowired
private LoggerAction loggerAction;

@Test
void updateAddress() {
loggerAction.updateAddress("朝阳小区1号", "光明小区1号");
}

@Test
void updateNewAddress() {
loggerAction.updateNewAddress("幸福小区1号");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,34 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lzhpo.logger.listener;
package com.lzhpo.logger;

import com.lzhpo.logger.LoggerEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
* <pre>
* {@code
* @Component
* public class LoggerListener implements ApplicationListener<LoggerEvent> {
*
* @Override
* public void onApplicationEvent(LoggerEvent event) {
* log.info("Received LoggerEvent: {}", event);
* log.info(event.getMessage());
* }
* }
* }
* </pre>
*
* @author lzhpo
* @see org.springframework.context.ApplicationListener
*/
@Slf4j
@Component
public class LoggerEventListener {
@TestConfiguration
public class LoggerListenerTest {

@Async
@EventListener
public void process(LoggerEvent event) {
log.info("Received LoggerEvent: {}", event);
Expand Down
Loading

0 comments on commit 8b228ea

Please sign in to comment.