solon框架AopContext各接口指北

AopContext接口

beanMake(Class<?> clz)

使用场景:

在开发插件(或在一些特殊条件下),自动扫描组件没有被扫描到,一般是因为要注册的组件没有在启动类的包下。

// 启动类所在包为 org.xxx
package org.xxx;

import org.noear.solon.Solon;
public class Main {
   
    public static void main(String[] args) {
   
        Solon.start(Main.class,args);
    }
}


// 组要注册的 controller 组件却在 com.test 包下,此时TestController 组件是不会被扫描到的
package com.test;

import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Mapping;

@Controller
public class TestController {
   
    @Mapping("t1")
    public String t1(){
   
        return "t1";
    }
}

由此可以使用 context.beanMake(TestController.class);来注册组件,并且会触发@Controller 的注解功能

beanBuilderAdd(Class anno, BeanBuilder builder)

使用场景:给带指定注解的类赋能(自定义注解),比如@MyController,@MyService 注解等

anno 参数为 注解类,

builder参数为 一个函数式接口,可以传递lambda 表达式或者实现了 BeanBuilder 接口的实现类

BeanBuilder类中的参数列表

void doBuild(Class<?> clz, BeanWrap bw, T anno) throws Throwable;

源码示例:

/** AopContext.java
* ::初始化(独立出 initialize,方便重写)
*/
protected void initialize() {
   

    // ...
    
    //注册 @Controller 构建器
    beanBuilderAdd(Controller.class, (clz, bw, anno) -> {
   
        new HandlerLoader(bw).load(Solon.app());
    });

    //注册 @ServerEndpoint 构建器
    beanBuilderAdd(ServerEndpoint.class, (clz, wrap, anno) -> {
   
        if (Listener.class.isAssignableFrom(clz)) {
   
            Listener l = wrap.raw();
            Solon.app().router().add(Utils.annoAlias(anno.value(), anno.path()), anno.method(), l);
        }
    });


    //注册 @Inject 注入器
    beanInjectorAdd(Inject.class, ((fwT, anno) -> {
   
        beanInject(fwT, anno.value(), anno.required(), anno.autoRefreshed());
    }));
}

执行了beanBuilderAdd方法后,传入的lambda 表达式 或者 实现了BeanBuilder 的类中的内容不会立即执行,它们会全部添加到beanBuilders 的Map集合中

/** BeanContainer.java
* bean 构建器
*/
protected final Map<Class<?>, BeanBuilder<?>> beanBuilders = new HashMap<>();

//
public <T extends Annotation> void beanBuilderAdd(Class<T> anno, BeanBuilder<T> builder) {
   
    beanBuilders.put(anno, builder);
}

那它们执行的时机是什么?通过查看beanBuilders.get()方法,可以看到获取它的时机。

源码分析

// AopContext.java
// 片段1
public void beanScan(Class<?> source) {
   
    //确定文件夹名
    if (source.getPackage() != null) {
   
        beanScan(source.getClassLoader(), source.getPackage().getName()); //跟踪这里
    }
}
/**  AopContext.java
*	// 片段2
* ::扫描源下的所有 bean 及对应处理
*/
public void beanScan(ClassLoader classLoader,String basePackage) {
   
    if (Utils.isEmpty(basePackage)) {
   
        return;
    }

    if (classLoader == null) {
   
        return;
    }

    String dir = basePackage.replace('.', '/');

    //扫描类文件并处理(采用两段式加载,可以部分bean先处理;剩下的为第二段处理)
    ScanUtil.scan(classLoader, dir, n -> n.endsWith(".class"))
        .stream()
        .sorted(Comparator.comparing(s -> s.length()))
        .forEach(name -> {
   
            String className = name.substring
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值