应该是在YuQ
中使用SpringBoot
吧,或者是在SpringBoot
中使用YuQ
,YuQ
直接引入Spring-Data-Jpa
会有个异常,虽然不影响运行,但是看着贼不爽,所以试试看看能不能把SpringBoot
整合进去
已知问题:SpringAop
不工作
1、把账号以及密码配置在application.yml
里
格式如下:
yuq:
art:
qq:
password:
master: 734669014
与其配置对应的配置类
@ConfigurationProperties(prefix = "yuq.art")
@Component
class ArtConfig {
var qq: Long = 0
var password: String = ""
var master: Long = 0
}
@ConfigurationProperties(prefix = "yuq.art")
@Component
public class ArtConfig {
private Long qq;
private String password;
private Long master;
}
2、启动类
由于YuQ
会在运行时对class进行字节码增强,其依赖于YuQ
的ClassLoader
,所以使用YuQ
的ClassLoader
来启动SpringBoot
@SpringBootApplication
class KuKuBotApplication
fun main(args: Array<String>) {
AppClassloader.registerBackList(listOf("ch.qos",
"org.springframework", "org.hibernate", "org.aopalliance", "com.querydsl"))
val appClassLoader = AppClassloader(KuKuBotApplication::class.java.classLoader)
Thread.currentThread().contextClassLoader = appClassLoader
val clazz = appClassLoader.loadClass("org.springframework.boot.SpringApplication")
val method = clazz.getMethod("run", Class::class.java, Array<String>::class.java)
method.invoke(null, KuKuBotApplication::class.java, args)
}
@SpringBootApplication
public class KuKuBotApplication {
public static void main(String[] args) {
try {
AppClassloader.registerBackList(List.of("ch.qos",
"org.springframework", "org.hibernate", "org.aopalliance", "com.querydsl"));
AppClassloader appClassLoader = new AppClassloader(KuKuBotApplication.class.getClassLoader());
Thread.currentThread().setContextClassLoader(appClassLoader);
SpringApplication.run(KuKuBotApplication.class);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
3、配置YuQ
以及Spring
扫包路径以及Spring的module
# 扫包路径
yu.scanPackages=me.kuku.yuq
# SpringMoudle类得全类名
yu.modules=me.kuku.yuq.config.SpringModule
yu.context.mode=single
开启spring
`bean`懒加载
spring:
main:
lazy-initialization: true
4、初始化YuQ
@Component
class ArtInit(
@Suppress("unused") private val springUtils: SpringUtils,
private val artConfig: ArtConfig
): ApplicationRunner {
private var app: DefaultApp? = null
private val log = LoggerFactory.getLogger(ArtInit::class.java)
override fun run(args: ApplicationArguments?) {
System.getProperties()["yuq.art.noUI"] = "${artConfig.qq}|${artConfig.password}|0"
val startTime = System.currentTimeMillis()
app = DefaultApp()
app?.start()
val overTime = System.currentTimeMillis()
log.info("Done! ${(overTime - startTime).toDouble() / 1000}s.")
println(" __ __ ____ \n" +
" \\ \\/ /_ __/ __ \\\n" +
" \\ / // / /_/ /\n" +
" /_/\\_,_/\\___\\_\\\n")
println("感谢您使用 YuQ 进行开发,在您使用中如果遇到任何问题,可以到 Github,Gitee 提出 issue,您也可以添加 YuQ 的开发交流群(696129128)进行交流。")
}
@PreDestroy
fun close() {
app?.stop()
}
}
class SpringModule: com.IceCreamQAQ.Yu.module.Module {
@Inject
private lateinit var yuContext: YuContext
override fun onLoad() {
val applicationContext = SpringUtils.applicationContext
val annotationConfigApplicationContext = applicationContext as AnnotationConfigApplicationContext
annotationConfigApplicationContext.registerBean("context", YuContext::class.java, Supplier { yuContext })
val names = applicationContext.beanDefinitionNames
val clazzList = mutableListOf<Class<*>>()
for (name in names) {
val clazzTemp = applicationContext.getType(name)
val ss = clazzTemp?.superclass
val list = listOf(clazzTemp, ss)
for (clazz in list) {
// if (clazz?.isAnnotationPresent(GroupController::class.java) == true || clazz?.isAnnotationPresent(PrivateController::class.java) == true ||
// clazz?.isAnnotationPresent(EventListener::class.java) == true || clazz?.isAnnotationPresent(JobCenter::class.java) == true) {
// clazzList.add(clazz)
// }
if (clazz?.isAnnotationPresent(Component::class.java) == true || clazz?.isAnnotationPresent(Controller::class.java) == true ||
clazz?.isAnnotationPresent(Service::class.java) == true) {
clazzList.add(clazz)
}
}
}
val classContextMap = yuContext::class.java.declaredFields.first { it.name == "classContextMap" }
.also { it.isAccessible = true }.get(yuContext) as MutableMap<String, ClassContext>
for (clazz in clazzList) {
val bean = applicationContext.getBean(clazz)
val name = clazz.name
val beanClazz = bean::class.java
yuContext.injectBean(bean)
val classContext =
ClassContext(name, beanClazz, false, null, bean, mutableMapOf("" to bean), null, null)
classContextMap[name] = classContext
}
}
}
@Component
public class ArtInit implements ApplicationRunner {
@Autowired
private SpringUtils springUtils;
@Autowired
private ArtConfig artConfig;
private DefaultApp app = null;
private final Logger log = (Logger) LoggerFactory.getLogger(ArtInit.class);
@Override
public void run(ApplicationArguments args) throws Exception {
System.getProperties().setProperty("yuq.art.noUI", artConfig.getQq() + "|" + artConfig.getPassword() + "|0");
long startTime = System.currentTimeMillis();
app = new DefaultApp();
app.start();
long overTime = System.currentTimeMillis();
log.info("Done! " + Long.valueOf((overTime - startTime)).doubleValue() / 1000 + "s.");
System.out.println(" __ __ ____ \n" +
" \\ \\/ /_ __/ __ \\\n" +
" \\ / // / /_/ /\n" +
" /_/\\_,_/\\___\\_\\\n");
System.out.println("感谢您使用 YuQ 进行开发,在您使用中如果遇到任何问题,可以到 Github,Gitee 提出 issue,您也可以添加 YuQ 的开发交流群(696129128)进行交流。");
}
@PreDestroy
public void close() {
app.stop();
}
}
public class SpringModule implements Module {
@Inject
private YuContext yuContext;
@Override
public void onLoad() {
ApplicationContext applicationContext = SpringUtils.applicationContext;
AnnotationConfigApplicationContext annotationConfigApplicationContext = (AnnotationConfigApplicationContext) applicationContext;
annotationConfigApplicationContext.registerBean("context", YuContext.class, () -> yuContext);
String[] names = applicationContext.getBeanDefinitionNames();
List<Class<?>> clazzList = new ArrayList<>();
for (String name : names) {
Class<?> clazzTemp = applicationContext.getType(name);
if (clazzTemp != null) {
Class<?> ss = clazzTemp.getSuperclass();
List<Class<?>> list = List.of(clazzTemp, ss);
for (Class<?> clazz : list) {
if (clazz.isAnnotationPresent(Component.class) || clazz.isAnnotationPresent(Controller.class)
|| clazz.isAnnotationPresent(Service.class)) {
clazzList.add(clazz);
}
}
}
}
Field[] fields = yuContext.getClass().getDeclaredFields();
Optional<Field> optional = Arrays.stream(fields).filter(it -> it.getName().equals("classContextMap")).findFirst();
if (optional.isPresent()) {
try {
Field field = optional.get();
field.setAccessible(true);
Map<String, ClassContext> classContextMap = (Map<String, ClassContext>) field.get(yuContext);
for (Class<?> clazz : clazzList) {
Object bean = applicationContext.getBean(clazz);
String name = clazz.getName();
Class<?> beanClazz = bean.getClass();
yuContext.injectBean(bean);
ClassContext classContext = new ClassContext(name, beanClazz, false, null, bean, Map.of("", bean), null, null);
classContextMap.put(name, classContext);
}
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
工具类SpringUtils
@Component
class SpringUtils: ApplicationContextAware {
companion object {
lateinit var applicationContext: ApplicationContext
inline fun <reified T: Any> getBean(name: String): T {
return applicationContext.getBean(name) as T
}
inline fun <reified T: Any> getBean() = applicationContext.getBean(T::class.java)
}
override fun setApplicationContext(applicationContext: ApplicationContext) {
Companion.applicationContext = applicationContext
}
}
@Component
public class SpringUtils implements ApplicationContextAware {
public static ApplicationContext applicationContext;
@Override
public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException {
SpringUtils.applicationContext = applicationContext;
}
}