基于注解配置扫描包

基于注解配置扫描包

大家好呀,我是小笙,我想单独讲一下通过注解的读取来完成扫描包,我此节只是描述简易的过程,加深理解!

自定义注解

自定义注解:可以通过指定 value 来指定bean对象 id,可是怎么实现呢?

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyComponent {
    String value() default  "";
}

扫描的包

需要被扫描的包可以自己随意定义,注意一点:idea 编译后不会把空文件夹加载到资源路径
在这里插入图片描述

配置文件

配置文件不具有spring特性,完全是通过dom4j技术读取操作

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
    <bean base="com.Al_tair.mySpringCompoent2"/>
</beans>

测试文件

创建ioc容器的时候传入xml 配置文件名

public class Test1 {
    @Test
    public void test(){
        MyApplicationContextByMyBean ioc = new MyApplicationContextByMyBean("myBean.xml");
        Dog dog = ioc.getBean("dogValue", Dog.class);
        System.out.println(dog);

        List<Object> list = ioc.listIocObject();
        System.out.println(list);
    }
}

ioc容器(重点)

ioc 容器是本节实现扫描包的重点知识!!

public class MyApplicationContextByMyBean {
    /**
     * 扫描包内类全路径
     */
    private List<String> list = new ArrayList<>();

    /**
     * 模拟ioc容器:
     */
    private ConcurrentHashMap<String,Object> ioc = new ConcurrentHashMap<>();

    public MyApplicationContextByMyBean(String myBean) {
        // 1.获取myBean的资源文件位置
        URL resource = MyApplicationContextByMyBean.class.getResource("/" + myBean);

        // 2.通过dom4j解析技术读取myBean.xml文件
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(resource);
            Element rootElement = document.getRootElement();
            // 3.解析得到对象的需要扫描的类路径,对象的属性
            //  暂时获取第一个bean对象
            Element bean = (Element)rootElement.elements("bean").get(0);
            String base = bean.attributeValue("base"); // 需要扫描的类路径 com.Al_tair.mySpringCompoent2.scanPackage
            File files = new File(MyApplicationContextByMyBean.class.getResource("/" + base.replace(".", "/")).getFile());

            // 扫描所有包以及子包下的类,返回全路径
            scanFiles(files);
            for (String s : list) {
                Class<?> aClass = Class.forName(s);
                boolean hasAnnotation = aClass.isAnnotationPresent(MyComponent.class);
                if(hasAnnotation){
                    String value = aClass.getAnnotation(MyComponent.class).value();
                    Object o = aClass.newInstance();
                    if("".equals(value)){
                    	// 将类的首字母小写
                        ioc.put(StringUtils.uncapitalize(s.substring(s.lastIndexOf(".") + 1)),o);
                    }else{
                    	// 将注解里的value值存入
                        ioc.put(value,o);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 扫描所有包以及子包下的类,返回所有被注解标识的单例bean对象的全路径
     * @param files 传入需要扫描的文件
     */
    private void scanFiles(File files){
        File[] f = files.listFiles();
        for (File file : f) {
            if(file.isDirectory()){
                scanFiles(file);
            }else{
                String absolutePath = file.getAbsolutePath();
                if(absolutePath.endsWith("class")) {
                    list.add(absolutePath.substring(absolutePath.lastIndexOf("\\com") + 1, absolutePath.lastIndexOf(".class")).
                            replace("\\","."));
                }
            }
        }
    }

    /**
     * 从ioc容器中获取Bean对象
     * @param key
     * @return
     */
    public Object getBean(String key){
        if(ioc.containsKey(key)){
            return ioc.get(key);
        }else{
            return null;
        }
    }

    public <T>T getBean(String key,Class<T> t){
        if(ioc.containsKey(key)){
            return (T)ioc.get(key);
        }else{
            return null;
        }
    }

    /**
     * @return 返回容器中所有的对象
     */
    public List<Object> listIocObject(){
        List<Object> l = new ArrayList<>();
        for (Object value : ioc.values()) {
            l.add(value);
        }
        return l;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Al_tair

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值