forked from mercyblitz/java-training-camp
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
基于 Byte Buddy 实现 Spring WebMVC Controller 拦截日志
- Loading branch information
Showing
7 changed files
with
176 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
...ain/java/com/acme/biz/web/configuration/AbstractAnnotationByteBuddyBeanPostProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package com.acme.biz.web.configuration; | ||
|
||
import net.bytebuddy.dynamic.DynamicType; | ||
import org.springframework.beans.BeansException; | ||
import org.springframework.beans.factory.BeanClassLoaderAware; | ||
import org.springframework.beans.factory.BeanCreationException; | ||
import org.springframework.beans.factory.BeanFactory; | ||
import org.springframework.beans.factory.BeanFactoryAware; | ||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory; | ||
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; | ||
|
||
import java.lang.annotation.Annotation; | ||
import java.lang.reflect.Method; | ||
|
||
/** | ||
* 基于{@link net.bytebuddy.ByteBuddy}实现的注解拦截 | ||
* | ||
* @author <a href="mailto:maimengzzz@gmail.com">韩超</a> | ||
* @since 1.0.0 | ||
*/ | ||
public abstract class AbstractAnnotationByteBuddyBeanPostProcessor<A extends Annotation> implements InstantiationAwareBeanPostProcessor, | ||
BeanClassLoaderAware, BeanFactoryAware { | ||
|
||
private ClassLoader classLoader; | ||
private AutowireCapableBeanFactory autowireCapableBeanFactory; | ||
@Override | ||
public void setBeanClassLoader(ClassLoader classLoader) { | ||
this.classLoader = classLoader; | ||
} | ||
|
||
@Override | ||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException { | ||
this.autowireCapableBeanFactory = (AutowireCapableBeanFactory) beanFactory; | ||
} | ||
|
||
@Override | ||
public Object postProcessBeforeInstantiation(Class<?> beanType, String beanName) throws BeansException { | ||
if (hasLogAnnotatedMethod(beanType, getAnnotationClass())) { | ||
Class<?> dynamicType = doIntercept(beanType).load(this.classLoader) | ||
.getLoaded(); | ||
try { | ||
return this.autowireCapableBeanFactory.createBean(dynamicType); | ||
} catch (Exception e) { | ||
throw new BeanCreationException(e.getMessage()); | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
|
||
protected abstract DynamicType.Unloaded<?> doIntercept(Class<?> beanType); | ||
|
||
protected abstract Class<A> getAnnotationClass(); | ||
|
||
protected ClassLoader getClassLoader() { | ||
return classLoader; | ||
} | ||
|
||
protected AutowireCapableBeanFactory getAutowireCapableBeanFactory() { | ||
return autowireCapableBeanFactory; | ||
} | ||
|
||
/** | ||
* 是否存在被指定注解标记的方法 | ||
* @param beanClass 被代理的bean class | ||
* @param annotationClass 注解 | ||
* @return 存在与否 | ||
*/ | ||
public boolean hasLogAnnotatedMethod(Class<?> beanClass, Class<A> annotationClass) { | ||
Method[] methods = beanClass.getDeclaredMethods(); | ||
for (Method method : methods) { | ||
if (method.isAnnotationPresent(annotationClass)) | ||
return true; | ||
} | ||
return false; | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
...roject/biz-web/src/main/java/com/acme/biz/web/configuration/LoggingBeanPostProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package com.acme.biz.web.configuration; | ||
|
||
import com.acme.biz.web.interceptor.LoggingInterceptor; | ||
import net.bytebuddy.ByteBuddy; | ||
import net.bytebuddy.dynamic.DynamicType; | ||
import net.bytebuddy.implementation.MethodDelegation; | ||
import net.bytebuddy.matcher.ElementMatchers; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
/** | ||
* TODO | ||
* | ||
* @author <a href="mailto:maimengzzz@gmail.com">韩超</a> | ||
* @since 1.0.0 | ||
*/ | ||
@Configuration | ||
public class LoggingBeanPostProcessor extends AbstractAnnotationByteBuddyBeanPostProcessor<LoggingInterceptor.Log> { | ||
|
||
|
||
private final LoggingInterceptor loggingInterceptor = new LoggingInterceptor(); | ||
|
||
@Override | ||
protected DynamicType.Unloaded<?> doIntercept(Class<?> beanType) { | ||
return new ByteBuddy() | ||
.subclass(beanType) | ||
.method(ElementMatchers.isAnnotatedWith(LoggingInterceptor.Log.class)) | ||
.intercept(MethodDelegation.to(this.loggingInterceptor)) | ||
.make(); | ||
} | ||
|
||
@Override | ||
protected Class<LoggingInterceptor.Log> getAnnotationClass() { | ||
return LoggingInterceptor.Log.class; | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
...rc/biz-project/biz-web/src/main/java/com/acme/biz/web/interceptor/LoggingInterceptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package com.acme.biz.web.interceptor; | ||
|
||
import net.bytebuddy.implementation.bind.annotation.Origin; | ||
import net.bytebuddy.implementation.bind.annotation.RuntimeType; | ||
import net.bytebuddy.implementation.bind.annotation.SuperCall; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
import java.lang.reflect.Method; | ||
import java.util.concurrent.Callable; | ||
|
||
/** | ||
* TODO | ||
* | ||
* @author <a href="mailto:maimengzzz@gmail.com">韩超</a> | ||
* @since 1.0.0 | ||
*/ | ||
public class LoggingInterceptor { | ||
|
||
private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class); | ||
|
||
@RuntimeType | ||
public Object doLog(@Origin Method method, @SuperCall Callable<?> callable) { | ||
// intercept any method of any signature | ||
logger.info("before invoke ..."); | ||
long start = System.currentTimeMillis(); | ||
try { | ||
return callable.call(); | ||
} catch (Exception e) { | ||
logger.error("error occupied", e); | ||
throw new RuntimeException(e); | ||
} finally { | ||
System.out.println(method + "invoke finished, it took " + (System.currentTimeMillis() - start)); | ||
} | ||
} | ||
|
||
@Target({ElementType.TYPE, ElementType.METHOD}) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface Log { | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters