Skip to content

Commit

Permalink
work-8
Browse files Browse the repository at this point in the history
  • Loading branch information
liqi19950722 committed Dec 4, 2022
1 parent c9a4b98 commit 17d99c5
Show file tree
Hide file tree
Showing 13 changed files with 404 additions and 0 deletions.
25 changes: 25 additions & 0 deletions work-8/biz-app/pom.xml
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 work-8/biz-app/src/main/java/com/acme/biz/BizApplication.java
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);
}
}


39 changes: 39 additions & 0 deletions work-8/biz-app/src/main/java/com/acme/biz/Demo.java
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);
}

}
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;
}
}
}
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 work-8/biz-app/src/main/java/com/acme/biz/domain/User.java
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 + '\'' +
'}';
}
}
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 {
}
}
}
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 {
}
}
}
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;
}

}
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);
}
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);
}
}
4 changes: 4 additions & 0 deletions work-8/biz-app/src/main/resources/application.yaml
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
Loading

0 comments on commit 17d99c5

Please sign in to comment.