-
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.
- Loading branch information
1 parent
c9a4b98
commit 17d99c5
Showing
13 changed files
with
404 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>com.acme.biz</groupId> | ||
<artifactId>work-8</artifactId> | ||
<version>1.0-SNAPSHOT</version> | ||
</parent> | ||
|
||
<artifactId>biz-app</artifactId> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-web</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>net.bytebuddy</groupId> | ||
<artifactId>byte-buddy</artifactId> | ||
</dependency> | ||
</dependencies> | ||
|
||
</project> |
36 changes: 36 additions & 0 deletions
36
work-8/biz-app/src/main/java/com/acme/biz/BizApplication.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,36 @@ | ||
package com.acme.biz; | ||
|
||
import com.acme.biz.interceptor.bytebuddy.spring.ServiceLoggerBeanPostProcessor; | ||
import org.springframework.beans.factory.config.BeanDefinition; | ||
import org.springframework.beans.factory.support.BeanDefinitionBuilder; | ||
import org.springframework.beans.factory.support.BeanDefinitionRegistry; | ||
import org.springframework.boot.SpringApplication; | ||
import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
import org.springframework.boot.context.properties.ConfigurationPropertiesScan; | ||
import org.springframework.context.annotation.Import; | ||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; | ||
import org.springframework.core.type.AnnotationMetadata; | ||
|
||
@SpringBootApplication | ||
@ConfigurationPropertiesScan | ||
@Import(value = {ServiceLoggerBeanPostProcessorRegistrar.class}) | ||
public class BizApplication { | ||
public static void main(String[] args) { | ||
SpringApplication.run(BizApplication.class, args); | ||
} | ||
} | ||
|
||
|
||
class ServiceLoggerBeanPostProcessorRegistrar implements ImportBeanDefinitionRegistrar { | ||
|
||
|
||
|
||
@Override | ||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { | ||
BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(ServiceLoggerBeanPostProcessor.class).getBeanDefinition(); | ||
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); | ||
registry.registerBeanDefinition("ServiceLoggerBeanPostProcessor", beanDefinition); | ||
} | ||
} | ||
|
||
|
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,39 @@ | ||
package com.acme.biz; | ||
|
||
import com.acme.biz.domain.User; | ||
import com.acme.biz.interceptor.bytebuddy.ServiceLoggerInterceptor; | ||
import com.acme.biz.service.UserService; | ||
import com.acme.biz.service.impl.UserServiceImpl; | ||
import net.bytebuddy.ByteBuddy; | ||
import net.bytebuddy.implementation.MethodDelegation; | ||
import net.bytebuddy.implementation.bind.annotation.Pipe; | ||
import net.bytebuddy.matcher.ElementMatchers; | ||
|
||
import java.lang.reflect.InvocationTargetException; | ||
import java.util.function.Function; | ||
|
||
public class Demo { | ||
static ClassLoader classLoader = Demo.class.getClassLoader(); | ||
|
||
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { | ||
UserService userService = new UserServiceImpl(); | ||
|
||
ByteBuddy byteBuddy = new ByteBuddy(); | ||
Class<? extends UserService> clazz = byteBuddy.subclass(UserService.class) | ||
.name(UserService.class.getName() + "ByteBuddy") | ||
.method(ElementMatchers.isDeclaredBy(UserService.class)) | ||
.intercept(MethodDelegation.withDefaultConfiguration() | ||
.withBinders(Pipe.Binder.install(Function.class)) | ||
.to(new ServiceLoggerInterceptor(userService))) | ||
.make() | ||
.load(classLoader) | ||
.getLoaded(); | ||
|
||
UserService proxy = clazz.getDeclaredConstructor().newInstance(); | ||
User user = new User(); | ||
user.setId(1L); | ||
user.setUserName("张三"); | ||
proxy.registerUser(user); | ||
} | ||
|
||
} |
39 changes: 39 additions & 0 deletions
39
work-8/biz-app/src/main/java/com/acme/biz/configuration/ByteBuddyProperties.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,39 @@ | ||
package com.acme.biz.configuration; | ||
|
||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
|
||
@ConfigurationProperties(prefix="bytebuddy") | ||
public class ByteBuddyProperties { | ||
|
||
private Logging logging = new Logging(); | ||
|
||
public Logging getLogging() { | ||
return logging; | ||
} | ||
|
||
public void setLogging(Logging logging) { | ||
this.logging = logging; | ||
} | ||
|
||
public static class Logging { | ||
|
||
private String service; | ||
private String controller; | ||
|
||
public String getService() { | ||
return service; | ||
} | ||
|
||
public void setService(String service) { | ||
this.service = service; | ||
} | ||
|
||
public String getController() { | ||
return controller; | ||
} | ||
|
||
public void setController(String controller) { | ||
this.controller = controller; | ||
} | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
work-8/biz-app/src/main/java/com/acme/biz/controller/UserController.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,21 @@ | ||
package com.acme.biz.controller; | ||
|
||
import com.acme.biz.domain.User; | ||
import com.acme.biz.service.UserService; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
public class UserController { | ||
|
||
@Autowired | ||
private UserService userService; | ||
|
||
@PostMapping(value = "/register") | ||
public void register(@RequestBody User user) { | ||
|
||
userService.registerUser(user); | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
work-8/biz-app/src/main/java/com/acme/biz/domain/User.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,30 @@ | ||
package com.acme.biz.domain; | ||
|
||
public class User { | ||
private Long id ; | ||
private String userName; | ||
|
||
public Long getId() { | ||
return id; | ||
} | ||
|
||
public void setId(Long id) { | ||
this.id = id; | ||
} | ||
|
||
public String getUserName() { | ||
return userName; | ||
} | ||
|
||
public void setUserName(String userName) { | ||
this.userName = userName; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "User{" + | ||
"id=" + id + | ||
", userName='" + userName + '\'' + | ||
'}'; | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
...biz-app/src/main/java/com/acme/biz/interceptor/bytebuddy/ControllerLoggerInterceptor.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,29 @@ | ||
package com.acme.biz.interceptor.bytebuddy; | ||
|
||
import net.bytebuddy.implementation.bind.annotation.AllArguments; | ||
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.reflect.Method; | ||
import java.util.Arrays; | ||
import java.util.concurrent.Callable; | ||
|
||
public class ControllerLoggerInterceptor { | ||
private static final Logger logger = LoggerFactory.getLogger(ServiceLoggerInterceptor.class); | ||
|
||
public ControllerLoggerInterceptor() { | ||
} | ||
|
||
@RuntimeType | ||
public Object log(@SuperCall Callable<Object> supercall, @AllArguments Object[] args, @Origin Method method) | ||
throws Exception { | ||
Arrays.stream(args).forEach(arg -> logger.info("{} 调用参数: {}", method, arg)); | ||
try { | ||
return supercall.call(); | ||
} finally { | ||
} | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
...-8/biz-app/src/main/java/com/acme/biz/interceptor/bytebuddy/ServiceLoggerInterceptor.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,32 @@ | ||
package com.acme.biz.interceptor.bytebuddy; | ||
|
||
import net.bytebuddy.implementation.bind.annotation.AllArguments; | ||
import net.bytebuddy.implementation.bind.annotation.Origin; | ||
import net.bytebuddy.implementation.bind.annotation.Pipe; | ||
import net.bytebuddy.implementation.bind.annotation.RuntimeType; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.lang.reflect.Method; | ||
import java.util.Arrays; | ||
import java.util.function.Function; | ||
|
||
public class ServiceLoggerInterceptor { | ||
private static final Logger logger = LoggerFactory.getLogger(ServiceLoggerInterceptor.class); | ||
private final Object object; | ||
|
||
public ServiceLoggerInterceptor(Object object) { | ||
this.object = object; | ||
} | ||
|
||
|
||
@RuntimeType | ||
public Object log(@Pipe Function<Object, Object> pipe, @AllArguments Object[] args, @Origin Method method) | ||
throws Exception { | ||
Arrays.stream(args).forEach(arg -> logger.info("{} 调用参数: {}", method, arg)); | ||
try { | ||
return pipe.apply(object); | ||
} finally { | ||
} | ||
} | ||
} |
90 changes: 90 additions & 0 deletions
90
...c/main/java/com/acme/biz/interceptor/bytebuddy/spring/ServiceLoggerBeanPostProcessor.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,90 @@ | ||
package com.acme.biz.interceptor.bytebuddy.spring; | ||
|
||
import com.acme.biz.configuration.ByteBuddyProperties; | ||
import com.acme.biz.interceptor.bytebuddy.ControllerLoggerInterceptor; | ||
import com.acme.biz.interceptor.bytebuddy.ServiceLoggerInterceptor; | ||
import net.bytebuddy.ByteBuddy; | ||
import net.bytebuddy.implementation.MethodDelegation; | ||
import net.bytebuddy.implementation.bind.annotation.Pipe; | ||
import net.bytebuddy.matcher.ElementMatchers; | ||
import org.springframework.beans.BeansException; | ||
import org.springframework.beans.factory.BeanClassLoaderAware; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.beans.factory.config.BeanPostProcessor; | ||
import org.springframework.context.ApplicationContext; | ||
import org.springframework.context.ApplicationContextAware; | ||
import org.springframework.core.annotation.MergedAnnotations; | ||
import org.springframework.stereotype.Controller; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.lang.reflect.InvocationTargetException; | ||
import java.util.function.Function; | ||
|
||
public class ServiceLoggerBeanPostProcessor implements BeanPostProcessor, BeanClassLoaderAware, ApplicationContextAware { | ||
|
||
@Autowired | ||
private ByteBuddyProperties byteBuddyProperties; | ||
|
||
@Override | ||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { | ||
String packageName = bean.getClass().getPackageName(); | ||
if (MergedAnnotations.from(bean.getClass(), MergedAnnotations.SearchStrategy.TYPE_HIERARCHY).isPresent(Service.class) | ||
&& packageName.startsWith(byteBuddyProperties.getLogging().getService())) { | ||
Class<?> superclass = bean.getClass().getInterfaces()[0]; // 假设只有一个 xxxService | ||
ByteBuddy byteBuddy = new ByteBuddy(); | ||
Class<?> clazz = byteBuddy.subclass(superclass) | ||
.name(superclass.getName() + "ByteBuddy") | ||
.method(ElementMatchers.isDeclaredBy(superclass)) | ||
.intercept(MethodDelegation.withDefaultConfiguration() | ||
.withBinders(Pipe.Binder.install(Function.class)) | ||
.to(new ServiceLoggerInterceptor(bean))) | ||
.make() | ||
.load(classLoader) | ||
.getLoaded(); | ||
try { | ||
Object proxy = clazz.getDeclaredConstructor().newInstance(); | ||
applicationContext.getAutowireCapableBeanFactory().autowireBean(proxy); | ||
return proxy; | ||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | | ||
NoSuchMethodException e) { | ||
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); | ||
} | ||
} | ||
|
||
if (MergedAnnotations.from(bean.getClass(), MergedAnnotations.SearchStrategy.TYPE_HIERARCHY).isPresent(Controller.class) | ||
&& packageName.startsWith(byteBuddyProperties.getLogging().getController())) { | ||
Class<?> beanClass = bean.getClass(); | ||
Class<?> clazz = new ByteBuddy().rebase(beanClass) | ||
.name(beanClass.getName() + "ByteBuddy") | ||
.method(ElementMatchers.any()) | ||
.intercept(MethodDelegation.to(new ControllerLoggerInterceptor())) | ||
.make() | ||
.load(classLoader) | ||
.getLoaded(); | ||
try { | ||
Object proxy = clazz.getDeclaredConstructor().newInstance(); | ||
applicationContext.getAutowireCapableBeanFactory().autowireBean(proxy); | ||
return proxy; | ||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | | ||
NoSuchMethodException e) { | ||
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); | ||
} | ||
} | ||
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); | ||
} | ||
|
||
private ClassLoader classLoader; | ||
|
||
@Override | ||
public void setBeanClassLoader(ClassLoader classLoader) { | ||
this.classLoader = classLoader; | ||
} | ||
|
||
private ApplicationContext applicationContext; | ||
|
||
@Override | ||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { | ||
this.applicationContext = applicationContext; | ||
} | ||
|
||
} |
7 changes: 7 additions & 0 deletions
7
work-8/biz-app/src/main/java/com/acme/biz/service/UserService.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,7 @@ | ||
package com.acme.biz.service; | ||
|
||
import com.acme.biz.domain.User; | ||
|
||
public interface UserService { | ||
void registerUser(User user); | ||
} |
18 changes: 18 additions & 0 deletions
18
work-8/biz-app/src/main/java/com/acme/biz/service/impl/UserServiceImpl.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,18 @@ | ||
package com.acme.biz.service.impl; | ||
|
||
import com.acme.biz.domain.User; | ||
import com.acme.biz.service.UserService; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
@Service(value = "userService") | ||
public class UserServiceImpl implements UserService { | ||
private List<User> userList = new ArrayList<>(); | ||
|
||
@Override | ||
public void registerUser(User user) { | ||
userList.add(user); | ||
} | ||
} |
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,4 @@ | ||
bytebuddy: | ||
logging: | ||
service: com.acme.biz.service | ||
controller: com.acme.biz.controller |
Oops, something went wrong.