当前位置: 首页 > news >正文

扫描包得到所有Bean的Class对象

文章目录

    • 1.任务介绍以及类加载器
        • 1.介绍
        • 2.类加载器
          • 1.介绍
          • 2.自己程序的类路径
    • 2.新建一个模块sun-spring用来写自己的spring容器
        • 1.新建模块
        • 2.查看是否交给父模块管理
        • 3.引入日志
    • 3.具体实现
        • 1.目录
        • 2.Component.java
        • 3.ComponentScan.java
        • 4.MonsterDao.java
        • 5.MonsterService.java
        • 6.SunSpringConfig.java
        • 7.SunSpringApplicationContext.java
        • 8.AppMain.java
        • 9.测试

1.任务介绍以及类加载器

1.介绍

CleanShot 2024-08-04 at 16.14.33@2x

2.类加载器
1.介绍

CleanShot 2024-08-04 at 16.15.23@2x

2.自己程序的类路径

CleanShot 2024-08-04 at 16.18.54@2x

2.新建一个模块sun-spring用来写自己的spring容器

1.新建模块

CleanShot 2024-08-04 at 16.23.42@2x

2.查看是否交给父模块管理

CleanShot 2024-08-04 at 16.24.09@2x

3.引入日志
    <dependencies><!-- 引入日志 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId><version>2.4.2</version></dependency></dependencies>

3.具体实现

1.目录

CleanShot 2024-08-04 at 17.14.21@2x

2.Component.java
package com.sunxiansheng.sunspring.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 组件注解:指定要自动创建bean对象的类,还可以自定义value作为创建bean对象的id** @author 孙显圣* @version 1.0*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {String value() default "";
}
3.ComponentScan.java
package com.sunxiansheng.sunspring.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 容器扫描的注解:通过value可以指定要扫描的包* @author sunxiansheng*/
@Target(ElementType.TYPE) // 作用在类上
@Retention(RetentionPolicy.RUNTIME) // 运行时生效
public @interface ComponentScan {String packagePath() default "";
}
4.MonsterDao.java
package com.sunxiansheng.sunspring.compent;import com.sunxiansheng.sunspring.annotation.Component;/*** Description: 怪物数据访问层* @Author sun* @Create 2024/8/4 16:34* @Version 1.0*/
@Component(value = "monsterDao")
public class MonsterDao {
}
5.MonsterService.java
package com.sunxiansheng.sunspring.compent;import com.sunxiansheng.sunspring.annotation.Component;/*** Description: 怪物服务* @Author sun* @Create 2024/8/4 16:31* @Version 1.0*/
// 自定义注解:将MonsterService类交给自定义Spring容器管理
// 如果指定value属性,则使用value属性值作为bean的id,否则使用类名首字母小写作为bean的id
@Component(value = "monsterService")
public class MonsterService {
}
6.SunSpringConfig.java
package com.sunxiansheng.sunspring.ioc;import com.sunxiansheng.sunspring.annotation.ComponentScan;/*** Description: 自定义Spring配置类* @Author sun* @Create 2024/8/4 16:29* @Version 1.0*/
@ComponentScan(packagePath = "com.sunxiansheng.sunspring.compent") //自定义注解:指定要扫描的包
public class SunSpringConfig {}
7.SunSpringApplicationContext.java
package com.sunxiansheng.sunspring.ioc;import com.sunxiansheng.sunspring.annotation.Component;
import com.sunxiansheng.sunspring.annotation.ComponentScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.File;
import java.net.URL;/*** Description: 自定义Spring容器* @Author sun* @Create 2024/8/4 16:35* @Version 1.0*/
public class SunSpringApplicationContext {private static final Logger log = LoggerFactory.getLogger(SunSpringApplicationContext.class);// 构造器,接收配置类的class对象public SunSpringApplicationContext(Class<?> configClass) throws ClassNotFoundException, InstantiationException, IllegalAccessException {// 传进来一个配置类的Class对象// 一、获取要扫描的包// 1.首先反射获取类的注解信息ComponentScan componentScan = configClass.getDeclaredAnnotation(ComponentScan.class);// 2.通过注解来获取要扫描的包的路径String path = componentScan.packagePath();log.info("要扫描的包路径为={}", path);// 二、得到要扫描包的.class文件对象,从而得到全路径进行反射// 1.获取App类加载器ClassLoader classLoader = SunSpringApplicationContext.class.getClassLoader();// 2.获取要扫描包的真实路径,默认刚开始在根目录下path = path.replace(".", "/");URL resource = classLoader.getResource(path);// 3.由该路径创建一个文件对象,可使用resource.getFile()将URL类型转化为String类型File file = new File(resource.getFile());// 4.遍历该文件夹下的所有.class文件对象if (file.isDirectory()) {File[] files = file.listFiles();for (File f : files) {// 反射注入容器// 1.获取所有文件的绝对路径String absolutePath = f.getAbsolutePath();// 只处理class文件if (absolutePath.endsWith(".class")) {// 2.分割出类名String className = extractClassName(absolutePath);// 3.得到全路径String fullPath = path.replace("/", ".") + "." + className;// 4.判断是否需要注入容器,查看有没有自定义的注解ComponentClass<?> aClass = classLoader.loadClass(fullPath);// 如果该类使用了注解Component则说明是一个spring beanif (aClass.isAnnotationPresent(Component.class)) {log.info("这是一个Spring bean={}", aClass);} else {log.info("这不是一个Spring bean={}", aClass);}}}}}// 返回容器中的对象public Object getBean(String name) {return null;}/*** 分割出类名* 类似于 com/sunxiansheng/sunspring/compent/MonsterService.class 的类名* @param filePath* @return*/private String extractClassName(String filePath) {// 获取最后一个 '/' 的位置int lastSlashIndex = filePath.lastIndexOf('/');// 获取最后一个 '.' 的位置int lastDotIndex = filePath.lastIndexOf('.');// 提取两者之间的字符串作为类名return filePath.substring(lastSlashIndex + 1, lastDotIndex);}}
8.AppMain.java
package com.sunxiansheng.sunspring;import com.sunxiansheng.sunspring.ioc.SunSpringApplicationContext;
import com.sunxiansheng.sunspring.ioc.SunSpringConfig;/*** Description:* @Author sun* @Create 2024/8/4 16:57* @Version 1.0*/
public class AppMain {public static void main(String[] args) {// 获取ioc容器并且传入配置类的class对象try {SunSpringApplicationContext sunSpringApplicationContext = new SunSpringApplicationContext(SunSpringConfig.class);} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {e.printStackTrace();}}}
9.测试

CleanShot 2024-08-04 at 17.17.59@2x


http://www.mrgr.cn/news/5868.html

相关文章:

  • Linux 信号 signal,sigaction,sigqueue,kill,相关函数
  • uni-app02
  • 安装 podman 与 podman-compose
  • SQL关键字检测持续优化,太难了
  • Pytorch:复写Dataset函数详解,以及Dataloader如何调用
  • 【数据分析】数据的计量尺度、数据集中趋势
  • 探索高效院内导航系统:最新技术解决方案与实战代码分享
  • 如何在算家云搭建模型mPLUG-Owl3(智能对话)
  • 第 10 章 正则表达式
  • Centos7.6-DNS服务安装与配置
  • mysql数据库调优
  • 模拟实现queue适配器【队列】【C++】
  • 【注解】@JsonProperty 详解
  • 【网络安全】副业兼职日入12k,网安人不接私活就太可惜了!
  • Stable Diffusion整合包与手动本地部署结合内网穿透远程AI绘画
  • 计算机毕业设计选题推荐-民宿可视化分析-Python爬虫-随机森林算法
  • oracle liunx 常用命令
  • HTML组件上传
  • ZooKeeper 的3种部署模式
  • 网络协议概述,ip协议,TCP协议,udp协议,二者区别,python中用socket类实现网络通信程序的编写(服务器套接字实现TCP编程,UDP编程)