五、Bean 的扫描方式与范围
容器型的框架,一般是要通过“配置”和“扫描”,获取类的元信息并做相关处理。
- 配置,一般是通过“约定”的文件目录或路径。像 Solon 就是约定
META-INF/solon/
目录为插件的配置文件 - 扫描,一般是深度遍历指定“包名”下的
.class
文件获取类名,再通过类名从类加载器里获取元信息
提醒:所需的注解能力,要在扫描之前完成注册(否则会失效)。
1、启动时扫描
启动时,主类所在包名下的类都会被扫描到(主类,提供了一个扫描范围)
package org.example.demo;
public class DemoApp{
public static void main(String[] args){
//
// DemoApp.clas 的作用,是提供一个扫描范围
//
Solon.start(DemoApp.class, args);
}
}
如果不在 org.example.demo
下的类也想被扫描怎么办???比如org.example.demo2
包名
- 可以把主类的包提到上一层
org.example
包下,这样可同时覆盖demo
和demo2
- 或者,通过导入器扩充扫描范围
2、通过导入器扩充扫描包的范围
- 注解模式
package org.example.demo;
//此时会增加 org.example.demo2 包的扫描
@Import(scanPackages = "org.example.demo2")
public class DemoApp{
public static void main(String[] args){
Solon.start(DemoApp.class, args);
}
}
- 手动模式
package org.example.demo;
//在应用启动时处理
public class DemoApp{
public static void main(String[] args){
Solon.start(DemoApp.class, args, app->{
//此时会增加 org.example.demo2 包的扫描(手动模式,在开发插件时会带来便利)
//app.context().beanScan("org.example.demo2");
//或者在插件加载完成后再扫描。避免有依赖未加载完成
app.onEvent(AppPluginLoadEndEvent.class, e->{
app.context().beanScan("org.example.demo2");
});
});
}
}
- 手动模式(for 插件)
//在插件启动时处理(如果你的类在一个插件里,这是最好的方案)
public class XPluginImp implements Plugin {
@Override
public void start(AppContext context) {
context.beanScan("org.example.demo2");
}
}
增加一个包的扫描可能浪费性能,如果只想导入一个类?
3、通过导入器导入1个类
- 注解模式
package org.example.demo;
//如果 UserServiceImpl 是在 org.example.demo2 包下,又想被扫描
@Import(UserServiceImpl.class)
public class DemoApp{
public static void main(String[] args){
Solon.start(DemoApp.class, args);
}
}
- 手动模式
package org.example.demo;
//在应用启动时处理
public class DemoApp{
public static void main(String[] args){
Solon.start(DemoApp.class, args, app->{
//相对来说,只导入一个类性能要好很多(随需而定)
app.onEvent(AppPluginLoadEndEvent.class, e->{
app.context().beanMake(UserServiceImpl.class);
});
});
}
}
- 手动模式(for 插件)
//在插件启动时处理(如果你的类在一个插件里,这是最好的方案)
public class XPluginImp implements Plugin {
@Override
public void start(AppContext context) {
context.beanMake(UserServiceImpl.class);
}
}
4、beanScan 和 beanMake 的选择?
- 如果类少,用 beanMake (性能好)
- 如果类多,用 beanScan (方便)