# 项目代码资源:
可能还在审核中,请等等。。。
https://download.csdn.net/download/chenhz2284/89432848
# 主项目
【pom.xml】
<groupId>com.chz</groupId>
<artifactId>chzopen_study</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>myBeanMain</module>
<module>myBeanBranch2</module>
</modules>
子模块【myBeanBranch2】
【pom.xml】
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.15.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.15.RELEASE</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>1.3.5</version>
</dependency>
【MyRegistrarAnnotation.java】
package com.chz.myBeanRegistrar.annotation;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.TYPE)
public @interface MyRegistrarAnnotation {
}
【MyImportBeanDefinitionRegistrar.java】
package com.chz.myBeanRegistrar.beanRegistrar;
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry,
BeanNameGenerator importBeanNameGenerator)
{
try {
// 这里开始扫描包里面的类
MyRegistrarScanner scanner = new MyRegistrarScanner(EnableBranchRegistrar.class.getPackageName());
List<Class<?>> targetClassList = scanner.scan();
for( Class<?> klass : targetClassList ){
// 扫到类之后注册成一个bean
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(klass);
registry.registerBeanDefinition(klass.getName(), beanDefinition);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args)
{
MyRegistrarAnnotation annotation = BranchRegistrarController.class.getAnnotation(MyRegistrarAnnotation.class);
System.out.println(annotation);
}
}
【BranchRegistrarController.java】
package com.chz.myBeanRegistrar.controller;
@Slf4j
@MyRegistrarAnnotation // 这里添加了我们自己的注解
@ResponseBody
@RequestMapping("/branch/registrar")
public class BranchRegistrarController {
public BranchRegistrarController()
{
log.info("chz >>> BranchRegistrarController.<init>()");
}
@GetMapping("/test1")
public String test1() {
return "test1: BranchRegistrarController";
}
}
【ClassScanner.java】
package com.chz.myBeanRegistrar.scan;
@Slf4j
public class ClassScanner {
private static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
private String basePackage;
private ClassLoader classLoader;
private Matcher matcher;
public ClassScanner(String basePackage, Matcher matcher)
{
this(basePackage, matcher, null);
}
public ClassScanner(String basePackage, Matcher matcher, ClassLoader classLoader)
{
this.basePackage = basePackage;
this.classLoader = classLoader!=null ? classLoader : this.getClass().getClassLoader();
this.matcher = matcher;
}
public List<Class<?>> scan() throws IOException {
List<Class<?>> candidates = new ArrayList<>();
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + convertPath(basePackage) + '/' + DEFAULT_RESOURCE_PATTERN;
ResourceLoader resourceLoader = new DefaultResourceLoader();
MetadataReaderFactory readerFactory = new SimpleMetadataReaderFactory(resourceLoader);
Resource[] resources = ResourcePatternUtils.getResourcePatternResolver(resourceLoader).getResources(packageSearchPath);
for (Resource resource : resources) {
Class<?> clazz = transformToClass(readerFactory.getMetadataReader(resource).getClassMetadata().getClassName());
if( matcher.match(clazz) ) {
candidates.add(clazz);
}
}
return candidates;
}
private Class<?> transformToClass(String className) {
Class<?> clazz = null;
try {
clazz = ClassUtils.forName(className, classLoader);
} catch (ClassNotFoundException e) {
log.info("未找到指定类", className, e);
} catch (NoClassDefFoundError e) {
log.info("未找到指定类", className, e);
throw e;
}
return clazz;
}
private String convertPath(String path) {
return StringUtils.replace(path, ".", "/");
}
public interface Matcher
{
boolean match(Class<?> clazz);
}
}
【MyRegistrarScanner.java】
package com.chz.myBeanRegistrar.scan;
public class MyRegistrarScanner {
private ClassScanner classScanner;
public MyRegistrarScanner(String basePackage){
classScanner = new ClassScanner(basePackage, new MoMatcher());
}
public MyRegistrarScanner(String basePackage, ClassLoader classLoader){
classScanner = new ClassScanner(basePackage, new MoMatcher(), classLoader);
}
public List<Class<?>> scan() throws IOException {
return (List<Class<?>>)(Object)classScanner.scan();
}
private static class MoMatcher implements ClassScanner.Matcher
{
@Override
public boolean match(Class<?> clazz) {
// 注意这些:要求class必须有【MyRegistrarAnnotation】注解
return isAbstract(clazz)==false && clazz.getAnnotation(MyRegistrarAnnotation.class)!=null;
}
}
public static boolean isAbstract(Class<?> clazz)
{
return Modifier.isAbstract(clazz.getModifiers());
}
}
【EnableBranchRegistrar.java】
package com.chz.myBeanRegistrar;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.TYPE)
@Import({
MyImportBeanDefinitionRegistrar.class, // 这里使用了 ImportBeanDefinitionRegistrar
})
public @interface EnableBranchRegistrar {
}
# 子模块:【myBeanMain】
【pom.xml】
<dependency>
<groupId>com.chz</groupId>
<artifactId>myBeanBranch2</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.3.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.3.12.RELEASE</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>
【application.properties】
server.port=8080
spring.application.name=myBeanMain
management.server.port=7001
management.endpoints.web.exposure.include=*
【MainBean.java】
package com.chz.myBeanMain.bean;
@Slf4j
@Getter
@Setter
@Component
public class MainBean {
@Autowired(required = false)
private NotAnnotatedBean notAnnotatedBean;
public MainBean()
{
log.info("chz >>> MainBean.<init>()");
}
@PostConstruct
public void init()
{
log.info("chz >>> MainBean.init()");
}
}
【NotAnnotatedBean.java】
package com.chz.myBeanMain.bean;
// 被【@Import】指过来的bean不需要添加【@Component】
@Slf4j
@Getter
@Setter
public class NotAnnotatedBean {
private String name = "I am " + this.getClass().getSimpleName();
public NotAnnotatedBean()
{
log.info("chz >>> NotAnnotatedBean.<init>()");
}
}
【MainConfiguration.java】
package com.chz.myBeanMain.config;
@Slf4j
@Configuration
public class MainConfiguration {
public MainConfiguration()
{
log.info("chz >>> MainConfiguration.<init>()");
}
}
【MainController.java】
package com.chz.myBeanMain.controller;
@Slf4j
@RestController
@RequestMapping("/main")
public class MainController {
@Autowired(required = false)
private MainBean mainBean;
@GetMapping("/notAnnotatedBean")
public String notAnnotatedBean() {
return "notAnnotatedBean: " + mainBean.getNotAnnotatedBean().getName();
}
}
【MyBeanMainTest.java】
package com.chz.myBeanMain;
@Import(NotAnnotatedBean.class) // 这里使用了@Import
@EnableBranchRegistrar // 这里使用了@ImportBeanDefinitionRegistrar
@SpringBootApplication
public class MyBeanMainTest {
public static void main(String[] args) {
SpringApplication.run(MyBeanMainTest.class, args);
}
}
# 运行
运行【MyBeanMainTest】,可以看到【BranchRegistrarController】确实被注册进来了
访问【http://localhost:8080/branch/registrar/test1】,正常显示