Spring boot 动态加载和部署导入的spring程序

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;

@Service
public class LoadService  {

    @Autowired
    private AnnotationConfigEmbeddedWebApplicationContext annotationConfigEmbeddedWebApplicationContext;
   
    public void register(File file) {
        try {
            file = new File("D:\\test1.1.0.jar");
			//查找依赖的jar包,同级目录下的lib/
            List<URL> dependencyJar = findDependencyJar(file);


            URL[] urls = dependencyJar.toArray(new URL[dependencyJar.size()]);
			//新建classloader 核心
            URLClassLoader urlClassLoader = new URLClassLoader(urls, annotationConfigEmbeddedWebApplicationContext.getClassLoader());

			//获取导入的jar的controller  service  dao 等类,并且创建BeanDefinition
            Set<BeanDefinition> beanDefinitions = getBeanDefinitions(urlClassLoader);
            
            beanDefinitions.forEach(item -> {
				//根据beanDefinition通过BeanFactory注册bean
                 annotationConfigEmbeddedWebApplicationContext.getDefaultListableBeanFactory().registerBeanDefinition(item.getBeanClassName(), item);
            });
			
			//修改BeanFactory的ClassLoader
            annotationConfigEmbeddedWebApplicationContext.getDefaultListableBeanFactory().setBeanClassLoader(urlClassLoader);
			//获取requestMappingHandlerMapping,用来注册HandlerMapping
			RequestMappingHandlerMapping requestMappingHandlerMapping=annotationConfigEmbeddedWebApplicationContext.getBean(RequestMappingHandlerMapping.class);
            beanDefinitions.forEach(item -> {
				
                String classname = item.getBeanClassName();
                try {
                    Class<?> c = Class.forName(classname, false, urlClassLoader);
                    Controller annotation = c.getAnnotation(Controller.class);
					//获取该bean 真正的创建
					Object proxy = annotationConfigEmbeddedWebApplicationContext.getBean(item.getBeanClassName());
					//如果此bean是Controller,则注册到RequestMappingHandlerMapping里面
                    if (annotation != null) {
						
                        Method getMappingForMethod = ReflectionUtils.findMethod(RequestMappingHandlerMapping.class, "getMappingForMethod", Method.class, Class.class);
                        getMappingForMethod.setAccessible(true);
                        try {
                            Method[] method_arr = c.getMethods();
                            for (Method m_d : method_arr) {
                                if (m_d.getAnnotation(RequestMapping.class) != null) {
                                    //创建RequestMappingInfo 
                                    RequestMappingInfo mapping_info = (RequestMappingInfo) getMappingForMethod.invoke(requestMappingHandlerMapping, m_d, c);
									//注册
                                    requestMappingHandlerMapping.registerMapping(mapping_info, proxy, m_d);
                                }

                            }

                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }
                }catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            });

        }catch (Exception e){
            e.printStackTrace();
        }

    }

    private static List<URL> findDependencyJar(File file) throws MalformedURLException {
        List<URL> list = new ArrayList<>();
        File parentFile = file.getParentFile();
        File libFile = new File(file.getParent() + File.separator + "lib");
        if (libFile.exists() && parentFile.isDirectory()) {
            for (File jar : libFile.listFiles()) {
                if (jar.isFile()
                        && jar.getName().toLowerCase().endsWith(".jar")
                        ) {
                    list.add(jar.toURI().toURL());
                }
            }
        }
        list.add(file.toURI().toURL());
        return list;

    }


    public  Set<BeanDefinition> getBeanDefinitions(ClassLoader classLoader) throws Exception {
        Set<BeanDefinition> candidates = new LinkedHashSet<>();

        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(classLoader);
        Resource[] resources = resourcePatternResolver.getResources("classpath*:com/xxx/**/*.**");

        MetadataReaderFactory metadata=new SimpleMetadataReaderFactory();
        for(Resource resource:resources) {
            MetadataReader metadataReader=metadata.getMetadataReader(resource);
            ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
            sbd.setResource(resource);
            sbd.setSource(resource);
            candidates.add(sbd);
        }
        for(BeanDefinition beanDefinition : candidates) {
            String classname=beanDefinition.getBeanClassName();
            Controller c=Class.forName(classname,false,classLoader).getAnnotation(Controller.class);
            Service s=Class.forName(classname,false,classLoader).getAnnotation(Service.class);
            Component component=Class.forName(classname,false,classLoader).getAnnotation(Component.class);
            if(c!=null ||s!=null ||component!=null)
                System.out.println(classname);
        }

        return candidates;
    }

}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值