Spring接口自动注入Bean

动态代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package cn.idea360.bridge.proxy;

import cn.idea360.bridge.api.UserService;
import cn.idea360.bridge.api.UserServiceImpl;
import cn.idea360.bridge.model.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
* @author cuishiying
*/
@Slf4j
public class ProxyTest {

UserService userService;

@BeforeEach
void init() throws Exception {
userService = new UserServiceImpl();
}

@Test
void dynamicProxy() throws Exception {
UserService instance = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(userService, args);
}
});
User user = instance.getUserById(1L);
log.info(user.toString());
}

@Test
void cglibProxy() throws Exception {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(userService.getClass());
enhancer.setCallback(new MethodInterceptor() {

@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
return method.invoke(userService, args);
}
});
UserService instance = (UserService) enhancer.create();
User user = instance.getUserById(1L);
log.info(user.toString());
}
}

简单注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.idea360</groupId>
<artifactId>http-bridge-dubbo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>http-bridge-dubbo</name>
<description>http-bridge-dubbo</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.6.13</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.idea360</groupId>
<artifactId>dubbo-api</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>cn.idea360.bridge.Application</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

</project>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package cn.idea360.bridge.support;

import cn.idea360.bridge.proxy.ProxyClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import java.util.LinkedHashSet;

/**
* @author cuishiying
*/
@Component
@Slf4j
public class ServiceBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor, ResourceLoaderAware, EnvironmentAware {

private ResourceLoader resourceLoader;

private Environment environment;

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
log.info("postProcessBeanDefinitionRegistry");
LinkedHashSet<BeanDefinition> candidateComponents = new LinkedHashSet<>();

ClassPathScanningCandidateComponentProvider scanner = getScanner();
scanner.setResourceLoader(this.resourceLoader);
scanner.addIncludeFilter(new AnnotationTypeFilter(ProxyClient.class));
// 包含三方jar(自定义注解)
candidateComponents.addAll(scanner.findCandidateComponents("cn.idea360"));
candidateComponents.addAll(scanner.findCandidateComponents("com.idea360"));
for (BeanDefinition candidateComponent : candidateComponents) {
String className = candidateComponent.getBeanClassName();
log.info("@ProxyClient className: {}", className);
Class beanClazz = ClassUtils.resolveClassName(className, null);
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(beanClazz);
GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition();
definition.getConstructorArgumentValues().addGenericArgumentValue(beanClazz);
definition.setBeanClass(ServiceFactory.class);
definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
registry.registerBeanDefinition(beanClazz.getSimpleName(), definition);
}
}

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
log.info("postProcessBeanFactory");
}

@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}

protected ClassPathScanningCandidateComponentProvider getScanner() {
return new ClassPathScanningCandidateComponentProvider(false, this.environment) {
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
boolean isCandidate = false;
if (beanDefinition.getMetadata().isIndependent()) {
if (!beanDefinition.getMetadata().isAnnotation()) {
isCandidate = true;
}
}
return isCandidate;
}
};
}

@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
}

工厂bean+动态代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package cn.idea360.bridge.support;

import cn.idea360.bridge.model.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.FactoryBean;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
* @author cuishiying
*/
public class ServiceFactory<T> implements FactoryBean<T> {

private Class<T> interfaceType;

public ServiceFactory(Class<T> interfaceType) {
this.interfaceType = interfaceType;
}

@Override
public T getObject() throws Exception {
InvocationHandler handler = new ServiceProxy<>(interfaceType);
return (T) Proxy.newProxyInstance(interfaceType.getClassLoader(),
new Class[] {interfaceType},handler);
}

@Override
public Class<?> getObjectType() {
return interfaceType;
}

@Override
public boolean isSingleton() {
return true;
}

@Slf4j
static class ServiceProxy<T> implements InvocationHandler {

private final Class<T> interfaceType;

public ServiceProxy(Class<T> interfaceType) {
this.interfaceType = interfaceType;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this,args);
}
log.info("interface: {}", interfaceType);
log.info("method: {}", method.getName());
log.info("parameterTypes: {}", method.getParameterTypes());
// args在http传输过程中对象参数会作为Map处理, 需要做序列化处理, 以便反序列化为对象参数, 而不是Map
log.info("args: {}", args);
User user = User.builder().name("当我遇上你").password("123").build();
return user;
}
}
}

单元测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package cn.idea360.bridge;

import cn.idea360.bridge.api.Role;
import cn.idea360.bridge.api.RoleService;
import cn.idea360.bridge.api.UserService;
import cn.idea360.bridge.model.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

@Slf4j
@SpringBootTest
class ApplicationTests {

@Resource
private UserService userService;
@Resource
private RoleService roleService;

@Test
void contextLoads() {
log.info("app start");
User user = userService.getUserById(1L);
log.info(user.toString());
roleService.addRole(Role.builder().name("ROLE_ADMIN").build());
}

}

参考Feign实现

org.mybatis.spring.annotation.MapperScan 类似

maven

1
2
3
4
5
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.0.4</version>
</dependency>

入口类

1
org.springframework.cloud.openfeign.EnableFeignClients

自定义实现

定义注解

1
2
3
4
5
6
7
8
9
10
11
12
package cn.idea360.bridge.proxy;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface ProxyClient {

String value() default "";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package cn.idea360.bridge.config;

import org.springframework.context.annotation.Import;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({HttpClientsRegistrar.class})
public @interface EnableProxy {

String[] value() default {};

String[] basePackages() default {};

Class<?>[] basePackageClasses() default {};
}

注册Bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package cn.idea360.bridge.config;

import cn.idea360.bridge.proxy.ProxyClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

/**
* @author cuishiying
*/
@Slf4j
public class HttpClientsRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {

private ResourceLoader resourceLoader;

private Environment environment;

@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}

@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}

@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
LinkedHashSet<BeanDefinition> candidateComponents = new LinkedHashSet<>();

ClassPathScanningCandidateComponentProvider scanner = getScanner();
scanner.setResourceLoader(this.resourceLoader);
scanner.addIncludeFilter(new AnnotationTypeFilter(ProxyClient.class));
Set<String> basePackages = getBasePackages(metadata);
for (String basePackage : basePackages) {
candidateComponents.addAll(scanner.findCandidateComponents(basePackage));
}
for (BeanDefinition candidateComponent : candidateComponents) {
if (candidateComponent instanceof AnnotatedBeanDefinition) {
// verify annotated class is an interface
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
Assert.isTrue(annotationMetadata.isInterface(), "@ProxyClient can only be specified on an interface");

Map<String, Object> attributes = annotationMetadata
.getAnnotationAttributes(ProxyClient.class.getCanonicalName());

registerProxyClient(registry, annotationMetadata, attributes);
}
}
}

private void registerProxyClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
String className = annotationMetadata.getClassName();
log.info("@ProxyClient className: {}", className);
Class clazz = ClassUtils.resolveClassName(className, null);
ConfigurableBeanFactory beanFactory = registry instanceof ConfigurableBeanFactory
? (ConfigurableBeanFactory) registry : null;
ProxyClientFactoryBean factoryBean = new ProxyClientFactoryBean();
factoryBean.setBeanFactory(beanFactory);
factoryBean.setType(clazz);
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(clazz, () -> {
return factoryBean.getObject();
});
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
definition.setLazyInit(true);

AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, className);

registry.registerBeanDefinition(className, beanDefinition);
}

protected ClassPathScanningCandidateComponentProvider getScanner() {
return new ClassPathScanningCandidateComponentProvider(false, this.environment) {
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
boolean isCandidate = false;
if (beanDefinition.getMetadata().isIndependent()) {
if (!beanDefinition.getMetadata().isAnnotation()) {
isCandidate = true;
}
}
return isCandidate;
}
};
}
protected Set<String> getBasePackages(AnnotationMetadata importingClassMetadata) {
Map<String, Object> attributes = importingClassMetadata
.getAnnotationAttributes(EnableProxy.class.getCanonicalName());

Set<String> basePackages = new HashSet<>();
for (String pkg : (String[]) attributes.get("value")) {
if (StringUtils.hasText(pkg)) {
basePackages.add(pkg);
}
}
for (String pkg : (String[]) attributes.get("basePackages")) {
if (StringUtils.hasText(pkg)) {
basePackages.add(pkg);
}
}

for (Class<?> clazz : (Class[]) attributes.get("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}

if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(importingClassMetadata.getClassName()));
}
return basePackages;
}
}

接口工厂Bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package cn.idea360.bridge.config;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
* @author cuishiying
*/
public class ProxyClientFactoryBean implements FactoryBean<Object>, InitializingBean, ApplicationContextAware, BeanFactoryAware {

private Class<?> type;
private BeanFactory beanFactory;
private ApplicationContext applicationContext;

@Override
public Object getObject() {
InvocationHandler handler = new ServiceProxy<>(type);
return Proxy.newProxyInstance(type.getClassLoader(),
new Class[] {type}, handler);
}

@Override
public Class<?> getObjectType() {
return type;
}

@Override
public boolean isSingleton() {
return true;
}

public void setType(Class<?> type) {
this.type = type;
}

public Class<?> getType() {
return type;
}

@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}

@Override
public void afterPropertiesSet() throws Exception {

}

@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
applicationContext = context;
beanFactory = context;
}
}

动态代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package cn.idea360.bridge.config;

import cn.idea360.bridge.model.User;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
* @author cuishiying
*/
@Slf4j
public class ServiceProxy<T> implements InvocationHandler {

private final Class<T> interfaceType;

public ServiceProxy(Class<T> interfaceType) {
this.interfaceType = interfaceType;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this,args);
}
log.info("interface: {}", interfaceType);
log.info("method: {}", method.getName());
log.info("parameterTypes: {}", method.getParameterTypes());
// args在http传输过程中对象参数会作为Map处理, 需要做序列化处理, 以便反序列化为对象参数, 而不是Map
log.info("args: {}", args);
User user = User.builder().name("当我遇上你").password("123").build();
return user;
}
}

接口定义

1
2
3
4
5
@ProxyClient
public interface UserService {

User getUserById(Long id);
}

启动类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package cn.idea360.bridge;

import cn.idea360.bridge.config.EnableProxy;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@EnableProxy(value = {"cn.idea360", "com.idea360"})
@SpringBootApplication
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

}

常用操作

扫描包含注解的component

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 类必须注解@Component或其他spring组件注解
*/
public Set<String> findAnnotatedClasses(Class<? extends Annotation> annotationType, String... packagesToBeScanned) {
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AnnotationTypeFilter(annotationType));
Set<String> ret = new HashSet<>();
for (String pkg : packagesToBeScanned)
{
Set<BeanDefinition> beanDefs = provider.findCandidateComponents(pkg);
beanDefs.stream()
.map(BeanDefinition::getBeanClassName)
.forEach(ret::add);
}
return ret;
}

扫描包含三方jar的class

1
2
3
4
5
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.0</version>
</dependency>
1
2
3
4
5
@Test
void scans() {
Set<Class<?>> classes = ClassScanner.scanPackage("cn.idea360");
log.info("@ProxyClient {}", classes.contains(RoleService.class));
}

BeanDefinitionRegistryPostProcessor 和ImportBeanDefinitionRegistrar 有什么区别

BeanDefinitionRegistryPostProcessor 和 ImportBeanDefinitionRegistrar 都是用于动态注册 Bean 到 Spring 容器的接口,但它们的使用场景和目的略有不同。

BeanDefinitionRegistryPostProcessor:

  • 作用:在 Spring 容器加载 Bean 定义之后,但在实例化 Bean 之前,允许对 BeanDefinition 进行修改或者注册新的 BeanDefinition。
  • 使用场景:适用于在应用启动时对现有 BeanDefinition 进行修改或者添加一些新的 BeanDefinition。
  • 例子:用于动态注册数据源、JdbcTemplate、事务管理器等。

ImportBeanDefinitionRegistrar:

  • 作用:允许在配置类中根据条件动态注册额外的 BeanDefinition。
  • 使用场景:适用于根据特定条件选择性地注册 BeanDefinition。通常与 @Import 注解一起使用,以实现特定的条件化配置。
  • 例子:用于基于某些条件选择性地注册一些 Bean。@Enablexxx

选择哪个更适合注册多数据源

  • 如果你的主要目标是在应用启动时动态注册多个数据源,那么使用 BeanDefinitionRegistryPostProcessor 更为直观和合适。
  • 如果你需要在配置类中根据条件来动态选择性地注册一些 Bean,那么 ImportBeanDefinitionRegistrar 可能更适合,尤其是当你希望将注册逻辑放在配置类中时。

在注册多数据源的场景中,通常会使用 BeanDefinitionRegistryPostProcessor,因为你可以在这个时机处理数据源的注册,而且这是一个更自然的选择。