diff --git a/.gitignore b/.gitignore
index a1c2a238a965f004ff76978ac1086aa6fe95caea..109980d29a5492627b058b9600f21cf2586f5a06 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,7 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
+
+#others
+*.idea
+*.iml
\ No newline at end of file
diff --git a/README.en.md b/README.en.md
deleted file mode 100644
index b44bb95f6a6327131f61e87c9243a96ef9e9ea59..0000000000000000000000000000000000000000
--- a/README.en.md
+++ /dev/null
@@ -1,36 +0,0 @@
-# spring-boot-starter-slf4j
-
-#### Description
-一个注解搞定日志
-
-#### Software Architecture
-Software architecture description
-
-#### Installation
-
-1. xxxx
-2. xxxx
-3. xxxx
-
-#### Instructions
-
-1. xxxx
-2. xxxx
-3. xxxx
-
-#### Contribution
-
-1. Fork the repository
-2. Create Feat_xxx branch
-3. Commit your code
-4. Create Pull Request
-
-
-#### Gitee Feature
-
-1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
-2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
-3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
-4. The most valuable open source project [GVP](https://gitee.com/gvp)
-5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
-6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a8918730a8033fda77bf54336219ff2539f694da
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,164 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.5.RELEASE
+
+
+ wiki.xsx
+ spring-boot-starter-slf4j
+ 1.0.0
+ jar
+ spring-boot-starter-slf4j
+ http://www.xsx.wiki
+ log project for Spring Boot
+
+
+ 1.8
+ 2.1.5.RELEASE
+ 3.25.0-GA
+ 1.18.8
+
+ true
+
+
+
+
+ The Apache Software License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+ repo
+
+
+
+ https://gitee.com/xsxgit/spring-boot-starter-slf4j
+ git@gitee.com:xsxgit/spring-boot-starter-slf4j.git
+ https://gitee.com/xsxgit/spring-boot-starter-slf4j.git
+
+
+
+ xsx
+ xsx344646090@vip.qq.com
+ http://www.xsx.wiki
+
+
+
+
+
+ release
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.8
+ true
+
+ oss
+ https://oss.sonatype.org/
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.1.0
+
+
+ package
+
+ jar-no-fork
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.1.0
+
+
+ -Xdoclint:none
+
+
+
+
+ package
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.6
+
+
+ verify
+
+ sign
+
+
+
+
+
+
+
+
+ oss
+ https://oss.sonatype.org/content/repositories/snapshots
+
+
+ oss
+ https://oss.sonatype.org/service/local/staging/deploy/maven2
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ ${java.version}
+ ${java.version}
+ UTF-8
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+ ${spring-boot.version}
+
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+ ${spring-boot.version}
+
+
+
+ org.javassist
+ javassist
+ ${javassist.version}
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ true
+
+
+
diff --git a/src/main/java/wiki/xsx/core/config/LogAutoConfiguration.java b/src/main/java/wiki/xsx/core/config/LogAutoConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..d5fe47856928b0c3463cf88f146ef82d9042eadc
--- /dev/null
+++ b/src/main/java/wiki/xsx/core/config/LogAutoConfiguration.java
@@ -0,0 +1,23 @@
+package wiki.xsx.core.config;
+
+import org.slf4j.Logger;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import wiki.xsx.core.log.LogProcessor;
+
+/**
+ * 日志自动装配
+ * @author xsx
+ * @date 2019/6/19
+ * @since 1.8
+ */
+@Configuration
+@ConditionalOnClass({Logger.class})
+public class LogAutoConfiguration {
+
+ @Bean
+ public LogProcessor logProcessor() {
+ return new LogProcessor();
+ }
+}
diff --git a/src/main/java/wiki/xsx/core/log/Level.java b/src/main/java/wiki/xsx/core/log/Level.java
new file mode 100644
index 0000000000000000000000000000000000000000..399c8af842579e5dbc7c8f3ba9fc4c6d9df8c63e
--- /dev/null
+++ b/src/main/java/wiki/xsx/core/log/Level.java
@@ -0,0 +1,26 @@
+package wiki.xsx.core.log;
+
+/**
+ * 日志级别
+ * @author xsx
+ * @date 2019/6/19
+ * @since 1.8
+ */
+public enum Level {
+ /**
+ * 调试级别
+ */
+ DEBUG,
+ /**
+ * 信息级别
+ */
+ INFO,
+ /**
+ * 警告级别
+ */
+ WARN,
+ /**
+ * 错误级别
+ */
+ ERROR;
+}
diff --git a/src/main/java/wiki/xsx/core/log/Log.java b/src/main/java/wiki/xsx/core/log/Log.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb38152249139fa274531f4c21f5b67d712e430a
--- /dev/null
+++ b/src/main/java/wiki/xsx/core/log/Log.java
@@ -0,0 +1,26 @@
+package wiki.xsx.core.log;
+
+import java.lang.annotation.*;
+
+/**
+ * 综合日志
+ * @author xsx
+ * @date 2019/6/18
+ * @since 1.8
+ */
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Log {
+ /**
+ * 业务名称
+ * @return
+ */
+ String value();
+
+ /**
+ * 日志级别
+ * @return
+ */
+ Level level() default Level.DEBUG;
+}
diff --git a/src/main/java/wiki/xsx/core/log/LogProcessor.java b/src/main/java/wiki/xsx/core/log/LogProcessor.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec9c9a703c54f539923c3fc239ba9b4b61534bcc
--- /dev/null
+++ b/src/main/java/wiki/xsx/core/log/LogProcessor.java
@@ -0,0 +1,284 @@
+package wiki.xsx.core.log;
+
+import javassist.CtMethod;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.Signature;
+import org.aspectj.lang.annotation.*;
+import wiki.xsx.core.support.MethodInfo;
+import wiki.xsx.core.support.MethodParser;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 日志处理器
+ * @author xsx
+ * @date 2019/6/17
+ * @since 1.8
+ */
+@Aspect
+@Slf4j
+public class LogProcessor {
+
+ /**
+ * 打印参数日志
+ * @param joinPoint 切入点
+ */
+ @Before("@annotation(ParamLog)")
+ public void beforPrint(JoinPoint joinPoint) {
+ Object[] args = joinPoint.getArgs();
+ Signature signature = joinPoint.getSignature();
+ String methodName = signature.getName();
+ try {
+ CtMethod method = MethodParser.getMethod(signature.getDeclaringTypeName(), methodName);
+ ParamLog paramLogAnnotation;
+ try {
+ paramLogAnnotation = (ParamLog) method.getAnnotation(ParamLog.class);
+ } catch (ClassNotFoundException e) {
+ paramLogAnnotation = null;
+ }
+ if (paramLogAnnotation!=null) {
+ this.print(
+ paramLogAnnotation.level(),
+ this.getBeforeInfo(
+ paramLogAnnotation.value(),
+ signature,
+ MethodParser.getMethodInfo(method),
+ args
+ )
+ );
+ }
+ } catch (Exception e) {
+ log.error("{}.{}方法错误", signature.getDeclaringTypeName(), methodName);
+ }
+ }
+
+ /**
+ * 打印返回值日志
+ * @param joinPoint 切入点
+ * @param result 返回结果
+ */
+ @AfterReturning(value = "@annotation(ResultLog)", returning = "result")
+ public void afterPrint(JoinPoint joinPoint, Object result) {
+ Signature signature = joinPoint.getSignature();
+ String methodName = signature.getName();
+ try {
+ CtMethod method = MethodParser.getMethod(signature.getDeclaringTypeName(), methodName);
+ ResultLog resultLogAnnotation;
+ try {
+ resultLogAnnotation = (ResultLog) method.getAnnotation(ResultLog.class);
+ } catch (ClassNotFoundException e) {
+ resultLogAnnotation = null;
+ }
+ if (resultLogAnnotation!=null) {
+ this.print(
+ resultLogAnnotation.level(),
+ this.getAfterInfo(
+ resultLogAnnotation.value(),
+ signature,
+ MethodParser.getMethodInfo(method),
+ result
+ )
+ );
+ }
+ } catch (Exception e) {
+ log.error("{}.{}方法错误", signature.getDeclaringTypeName(), methodName);
+ }
+ }
+
+ /**
+ * 打印异常日志
+ * @param joinPoint 切入点
+ * @param throwable 异常
+ */
+ @AfterThrowing(value = "@annotation(ThrowingLog)||@annotation(Log)", throwing = "throwable")
+ public void throwingPrint(JoinPoint joinPoint, Throwable throwable) {
+ Signature signature = joinPoint.getSignature();
+ String methodName = signature.getName();
+ try {
+ CtMethod method = MethodParser.getMethod(signature.getDeclaringTypeName(), methodName);
+ ThrowingLog throwingAnnotation;
+ try {
+ throwingAnnotation = (ThrowingLog) method.getAnnotation(ThrowingLog.class);
+ } catch (ClassNotFoundException e) {
+ throwingAnnotation = null;
+ }
+ if (throwingAnnotation!=null) {
+ log.error(
+ this.getThrowingInfo(
+ throwingAnnotation.value(),
+ signature,
+ MethodParser.getMethodInfo(method)
+ ),
+ throwable
+ );
+ }else {
+ Log logAnnotation;
+ try {
+ logAnnotation = (Log) method.getAnnotation(Log.class);
+ } catch (ClassNotFoundException e) {
+ logAnnotation = null;
+ }
+ if (logAnnotation!=null) {
+ log.error(
+ this.getThrowingInfo(
+ logAnnotation.value(),
+ signature,
+ MethodParser.getMethodInfo(method)
+ ),
+ throwable
+ );
+ }
+ }
+ } catch (Exception e) {
+ log.error("{}.{}方法错误", signature.getDeclaringTypeName(), methodName);
+ }
+ }
+
+ /**
+ * 打印环绕日志
+ * @param joinPoint 切入点
+ * @return 返回方法返回值
+ * @throws Throwable 异常
+ */
+ @Around(value = "@annotation(Log)")
+ public Object aroundPrint(ProceedingJoinPoint joinPoint) throws Throwable {
+ Object[] args = joinPoint.getArgs();
+ Signature signature = joinPoint.getSignature();
+ String methodName = signature.getName();
+ try {
+ CtMethod method = MethodParser.getMethod(signature.getDeclaringTypeName(), methodName);
+ Log logAnnotation;
+ try {
+ logAnnotation = (Log) method.getAnnotation(Log.class);
+ } catch (ClassNotFoundException e) {
+ logAnnotation = null;
+ }
+ if (logAnnotation!=null) {
+ this.print(
+ logAnnotation.level(),
+ this.getBeforeInfo(
+ logAnnotation.value(),
+ signature,
+ MethodParser.getMethodInfo(method),
+ args
+ )
+ );
+ }
+ Object result = joinPoint.proceed(args);
+ if (logAnnotation!=null) {
+ this.print(
+ logAnnotation.level(),
+ this.getAfterInfo(
+ logAnnotation.value(),
+ signature,
+ MethodParser.getMethodInfo(method),
+ result
+ )
+ );
+ }
+ return result;
+ } catch (Throwable e) {
+ log.error("{}.{}方法错误", signature.getDeclaringTypeName(), methodName);
+ throw e;
+ }
+ }
+
+ /**
+ * 获取日志信息字符串
+ * @param busName 业务名
+ * @param signature 签名信息
+ * @param methodInfo 方法信息
+ * @param params 参数值
+ * @return 返回日志信息字符串
+ */
+ private String getBeforeInfo(String busName, Signature signature, MethodInfo methodInfo, Object[] params) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("调用方法:【").append(this.createMethodStack(signature, methodInfo)).append("】,")
+ .append("业务名称:【").append(busName).append("】,").append("接收参数:【");
+ List paramNames = methodInfo.getParamNames();
+ int count = paramNames.size();
+ if (count>0) {
+ Map paramMap = new HashMap<>(count);
+ for (int i = 0; i < count; i++) {
+ paramMap.put(paramNames.get(i), params[i]);
+ }
+ return builder.append(paramMap).append("】").toString();
+ }
+ return builder.append("{}】").toString();
+ }
+
+ /**
+ * 获取日志信息字符串
+ * @param busName 业务名
+ * @param signature 签名信息
+ * @param methodInfo 方法信息
+ * @param result 返回结果
+ * @return 返回日志信息字符串
+ */
+ private String getAfterInfo(String busName, Signature signature, MethodInfo methodInfo, Object result) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("调用方法:【").append(this.createMethodStack(signature, methodInfo)).append("】,")
+ .append("业务名称:【").append(busName).append("】,").append("返回结果:【").append(result).append("】");
+ return builder.toString();
+ }
+
+ /**
+ * 获取日志信息字符串
+ * @param busName 业务名
+ * @param signature 签名信息
+ * @param methodInfo 方法信息
+ * @return 返回日志信息字符串
+ */
+ private String getThrowingInfo(String busName, Signature signature, MethodInfo methodInfo) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("调用方法:【").append(this.createMethodStack(signature, methodInfo)).append("】,")
+ .append("业务名称:【").append(busName).append("】,").append("异常信息:");
+ return builder.toString();
+ }
+
+ /**
+ * 创建方法栈
+ * @param signature 签名信息
+ * @param methodInfo 方法信息
+ * @return 返回栈信息
+ */
+ private StackTraceElement createMethodStack(Signature signature, MethodInfo methodInfo) {
+ return new StackTraceElement(
+ signature.getDeclaringTypeName(),
+ methodInfo.getMethodName(),
+ String.format("%s.java", signature.getDeclaringType().getSimpleName()),
+ methodInfo.getLineNumber()
+ );
+ }
+
+ /**
+ * 打印信息
+ * @param level 日志级别
+ * @param msg 输出信息
+ */
+ private void print(Level level, String msg) {
+ switch (level) {
+ case DEBUG: {
+ log.debug(msg);
+ break;
+ }
+ case INFO: {
+ log.info(msg);
+ break;
+ }
+ case WARN: {
+ log.warn(msg);
+ break;
+ }
+ case ERROR: {
+ log.error(msg);
+ break;
+ }
+ default:
+ }
+ }
+}
diff --git a/src/main/java/wiki/xsx/core/log/ParamLog.java b/src/main/java/wiki/xsx/core/log/ParamLog.java
new file mode 100644
index 0000000000000000000000000000000000000000..e1795ed843917cfeb4647f0243a88528938a61e9
--- /dev/null
+++ b/src/main/java/wiki/xsx/core/log/ParamLog.java
@@ -0,0 +1,26 @@
+package wiki.xsx.core.log;
+
+import java.lang.annotation.*;
+
+/**
+ * 参数日志
+ * @author xsx
+ * @date 2019/6/17
+ * @since 1.8
+ */
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface ParamLog {
+ /**
+ * 业务名称
+ * @return
+ */
+ String value();
+
+ /**
+ * 日志级别
+ * @return
+ */
+ Level level() default Level.DEBUG;
+}
diff --git a/src/main/java/wiki/xsx/core/log/ResultLog.java b/src/main/java/wiki/xsx/core/log/ResultLog.java
new file mode 100644
index 0000000000000000000000000000000000000000..19ee72be98b63c760f561810c3ffd3f76cf5ba75
--- /dev/null
+++ b/src/main/java/wiki/xsx/core/log/ResultLog.java
@@ -0,0 +1,26 @@
+package wiki.xsx.core.log;
+
+import java.lang.annotation.*;
+
+/**
+ * 结果日志
+ * @author xsx
+ * @date 2019/6/18
+ * @since 1.8
+ */
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface ResultLog {
+ /**
+ * 业务名称
+ * @return
+ */
+ String value();
+
+ /**
+ * 日志级别
+ * @return
+ */
+ Level level() default Level.DEBUG;
+}
diff --git a/src/main/java/wiki/xsx/core/log/ThrowingLog.java b/src/main/java/wiki/xsx/core/log/ThrowingLog.java
new file mode 100644
index 0000000000000000000000000000000000000000..08ad2800ed66d7869b094d11703e5f2943e6e7cd
--- /dev/null
+++ b/src/main/java/wiki/xsx/core/log/ThrowingLog.java
@@ -0,0 +1,20 @@
+package wiki.xsx.core.log;
+
+import java.lang.annotation.*;
+
+/**
+ * 异常日志
+ * @author xsx
+ * @date 2019/6/19
+ * @since 1.8
+ */
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface ThrowingLog {
+ /**
+ * 业务名称
+ * @return
+ */
+ String value();
+}
diff --git a/src/main/java/wiki/xsx/core/support/MethodInfo.java b/src/main/java/wiki/xsx/core/support/MethodInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..6e0351c4164ee2b18a570ebcc545ab532cd91efd
--- /dev/null
+++ b/src/main/java/wiki/xsx/core/support/MethodInfo.java
@@ -0,0 +1,39 @@
+package wiki.xsx.core.support;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 方法信息
+ * @author xsx
+ * @date 2019/6/19
+ * @since 1.8
+ */
+@Data
+public class MethodInfo {
+ /**
+ * 方法名称
+ */
+ private String methodName;
+ /**
+ * 参数列表
+ */
+ private List paramNames;
+ /**
+ * 方法行号
+ */
+ private Integer lineNumber;
+
+ /**
+ * 构造
+ * @param methodName 方法名称
+ * @param paramNames 参数列表
+ * @param lineNumber 方法行号
+ */
+ MethodInfo(String methodName, List paramNames, Integer lineNumber) {
+ this.methodName = methodName;
+ this.paramNames = paramNames;
+ this.lineNumber = lineNumber;
+ }
+}
diff --git a/src/main/java/wiki/xsx/core/support/MethodParser.java b/src/main/java/wiki/xsx/core/support/MethodParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..68a8950ec19593f0bfb17e0c7878e90779a73883
--- /dev/null
+++ b/src/main/java/wiki/xsx/core/support/MethodParser.java
@@ -0,0 +1,74 @@
+package wiki.xsx.core.support;
+
+import javassist.ClassPool;
+import javassist.CtMethod;
+import javassist.NotFoundException;
+import javassist.bytecode.LocalVariableAttribute;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 方法解析器
+ * @author xsx
+ * @date 2019/6/19
+ * @since 1.8
+ */
+public class MethodParser {
+
+ /**
+ * 类池
+ */
+ private final static ClassPool POOL = ClassPool.getDefault();
+
+ /**
+ * 获取调用方法
+ * @param className 全类名
+ * @param methodName 方法名称
+ * @return 返回对应方法
+ * @throws NotFoundException 未知方法异常
+ */
+ public static CtMethod getMethod(String className, String methodName) throws NotFoundException {
+ return POOL.get(className).getDeclaredMethod(methodName);
+ }
+
+ /**
+ * 获取方法信息
+ * @param className 全类名
+ * @param methodName 方法名称
+ * @return 返回方法信息
+ */
+ public static MethodInfo getMethodInfo(String className, String methodName) {
+ try {
+ return getMethodInfo(getMethod(className, methodName));
+ } catch (Exception e) {
+ return new MethodInfo(methodName, new ArrayList<>(0), -1);
+ }
+ }
+
+ /**
+ * 获取方法信息
+ * @param method 方法对象
+ * @return 返回方法信息
+ */
+ public static MethodInfo getMethodInfo(CtMethod method) {
+ try {
+ javassist.bytecode.MethodInfo methodInfo = method.getMethodInfo();
+ int lineNumber = methodInfo.getLineNumber(0);
+ List paramNames;
+ LocalVariableAttribute attribute = (LocalVariableAttribute) methodInfo.getCodeAttribute().getAttribute(LocalVariableAttribute.tag);
+ if (attribute!=null) {
+ int count = method.getParameterTypes().length;
+ paramNames = new ArrayList<>(count);
+ for (int i = 1; i <= count; i++) {
+ paramNames.add(attribute.variableName(i));
+ }
+ }else {
+ paramNames = new ArrayList<>(0);
+ }
+ return new MethodInfo(method.getName(), paramNames, lineNumber);
+ } catch (Exception e) {
+ return new MethodInfo(method.getName(), new ArrayList<>(0), -1);
+ }
+ }
+}
diff --git a/src/main/resources/META-INF/spring.factories b/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000000000000000000000000000000000000..ed41837496061f7055cc769adbfff08032bbe79a
--- /dev/null
+++ b/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+#log自动装配
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=wiki.xsx.core.config.LogAutoConfiguration
\ No newline at end of file