首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
V2EX  ›  问与答

求问 springboot 项目怎么加载 jar 包中的 bean

  •  
  •   tomoya92 · 105 天前 · 1584 次点击
    这是一个创建于 105 天前的主题,其中的信息可能已经有所发展或是发生改变。

    主项目 pybbs,启动类包名 co.yiiu.pybbs 配置了扫描包 @SpringBootApplication(scanBasePackages = "co.yiiu.pybbs")

    另外创建了一个 maven 项目,写了一个 bean,名包是 co.yiiu.pybbs.plugin 类上也加了 @Component 注解


    首先我把新建的 maven 项目通过 mvn install 安装到本地,然后在 pybbs 里通过 pom 引入,启动项目测试没有问题,可以扫描到新建包中的 bean 以及方法的调用


    然后我又通过 mvn assembly:assembly 把 pybbs 打包了,在 assembly 里配置了程序 jar 包和引入信赖 jar 包分享的方式来打包的,生成的目录中会有一个 lib 文件夹,然后我把新建的 maven 项目也打成 jar 包,然后拷贝到 pybbs/lib 目录中,启动项目就有问题了,spring 不会去扫描 jar 包中的 bean,方法也没有生效


    求问:

    spring 怎么加载外部 jar 包中的 bean 呢?

    下面有我两个项目的配置,大佬们帮忙看下是我哪配置错了吗?万分感谢!!!


    pybbs 中的 pom.xml build 配置

    <build>
    
        <finalName>pybbs</finalName>
    
        <resources>
          <resource>
            <directory>src/main/java</directory>
            <includes>
              <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
          </resource>
          <resource>
            <directory>src/main/resources</directory>
          </resource>
        </resources>
    
        <plugins>
    
          <!--springboot 插件
          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
          </plugin>-->
    
          <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.6</version>
            <configuration>
              <!-- 如果是 true 在打出来的包 /路径上面会增加这个 Assembly 的 id 显示-->
              <appendAssemblyId>false</appendAssemblyId>
              <descriptors>
                <!-- assembly 描述文件位置 -->
                <descriptor>src/main/resources/assembly.xml</descriptor>
              </descriptors>
              <!-- 打包完成后文件输出位置 这里为 target 目录-->
              <outputDirectory>${project.build.directory}</outputDirectory>
            </configuration>
          </plugin>
          <plugin>
            <!-- 主要用来打包主 jar-->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.6</version>
            <configuration>
              <archive>
                <manifest>
                  <!--启动文件入口类,就是 springboot 启动 main 方法所在类 -->
                  <mainClass>co.yiiu.pybbs.PybbsApplication</mainClass>
                  <!-- 主 jar 依赖的 jar 包路径-->
                  <classpathPrefix>lib/</classpathPrefix>
                  <addClasspath>true</addClasspath>
                </manifest>
                <!--<manifestEntries>
                  &lt;!&ndash; 在 Class-Path 下添加配置文件的路径 &ndash;&gt;
                  <Class-Path>resources</Class-Path>
                </manifestEntries>-->
              </archive>
              <!-- 不把配置文件和 html 文件打进主 jar 内-->
              <excludes>
                <exclude>*.java</exclude>
                <exclude>static/</exclude>
                <exclude>db/</exclude>
                <exclude>templates/</exclude>
                <exclude>*.yml</exclude>
                <exclude>*.txt</exclude>
                <exclude>logback.xml</exclude>
              </excludes>
            </configuration>
          </plugin>
    
          <!-- 打包发布时,跳过单元测试 -->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
              <skipTests>true</skipTests>
            </configuration>
          </plugin>
    
        </plugins>
      </build>
    

    assembly.xml 配置

    <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
    
      <id>package</id>
      <formats>
        <!-- 打包成目录,这里其实有很多选择,如 dir,jar,war,zip 等,我们这里选择先打成目录,到真正要用的时候可以打包成 zip-->
        <format>tar.gz</format>
        <!--<format>dir</format>-->
      </formats>
    
      <includeBaseDirectory>false</includeBaseDirectory>
    
      <fileSets>
        <!-- 把项目相关的说明文件,打包进 zip 文件的根目录 -->
        <fileSet>
          <directory>${project.basedir}</directory>
          <outputDirectory></outputDirectory>
          <excludes>
            <exclude>logback.xml</exclude>
            <exclude>static/**</exclude>
            <exclude>*.json</exclude>
            <exclude>pom.xml</exclude>
            <exclude>target/**</exclude>
            <exclude>mysql/**</exclude>
            <exclude>docs/**</exclude>
            <exclude>logs/**</exclude>
            <exclude>src/**</exclude>
            <exclude>sql/**</exclude>
            <exclude>.idea/**</exclude>
            <exclude>.gitignore</exclude>
            <exclude>.classpath</exclude>
            <exclude>.factorypath</exclude>
            <exclude>.project</exclude>
            <exclude>application.pid</exclude>
            <exclude>pybbs.iml</exclude>
            <exclude>pybbs.pid</exclude>
            <exclude>.settings/**</exclude>
            <exclude>Dockerfile</exclude>
            <exclude>docker-compose.yml</exclude>
            <exclude>application-docker.yml</exclude>
            <exclude>application-dev.yml</exclude>
          </excludes>
        </fileSet>
        <!-- 把项目的配置文件,打包进 zip 文件的根目录 -->
        <fileSet>
          <directory>${project.basedir}/src/main/resources</directory>
          <outputDirectory></outputDirectory>
          <excludes>
            <exclude>assembly.xml</exclude>
            <exclude>static/upload/**</exclude>
            <exclude>i18n/**</exclude>
          </excludes>
          <!--  <excludes>
               <exclude>**</exclude>
            </excludes>-->
        </fileSet>
        <!-- 把项目的脚本文件,打包进 zip 文件的 bin 目录-->
        <fileSet>
          <directory>${project.basedir}/src/main/bin</directory>
          <outputDirectory>bin</outputDirectory>
          <excludes>
            <exclude>target/**</exclude>
            <exclude>*.json</exclude>
            <exclude>static/**</exclude>
            <exclude>templates/**</exclude>
          </excludes>
        </fileSet>
      </fileSets>
    
      <dependencySets>
        <!-- 打包依赖文件,就是 maven 里面那一堆 jar 包-->
        <dependencySet>
          <outputDirectory>/lib</outputDirectory>
          <scope>runtime</scope>
          <!-- 除了主 jar 文件都打到 lib 目录下-->
          <excludes>
            <exclude>${project.groupId}:${project.artifactId}</exclude>
          </excludes>
        </dependencySet>
        <!-- 主 jar 打到根目录,因为 pom 文件中设置主 jar 的依赖包目录为 lib/-->
        <dependencySet>
          <outputDirectory>/</outputDirectory>
          <outputFileNameMapping>${artifact.artifactId}${dashClassifier?}.${artifact.extension}</outputFileNameMapping>
          <includes>
            <include>${project.groupId}:${project.artifactId}</include>
          </includes>
        </dependencySet>
      </dependencySets>
    </assembly>
    

    新建 maven 项目中 pom.xml build 节点配置

    <build>
        <finalName>pybbs-redis-cache-plugin</finalName>
        <plugins>
          <!-- 编译指定 jdk 版本号 -->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
              <source>1.8</source>
              <target>1.8</target>
              <encoding>UTF-8</encoding>
              <showWarnings>true</showWarnings>
            </configuration>
          </plugin>
          <!-- 部署带上源文件, 可以在引入依赖时看到源码, 以及源码上的注释信息 -->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <version>3.0.1</version>
            <configuration>
              <includePom>true</includePom>
              <excludeResources>true</excludeResources>
              <attach>true</attach>
            </configuration>
            <executions>
              <execution>
                <id>attach-sources</id>
                <goals>
                  <goal>jar</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    
    14 回复  |  直到 2019-06-08 09:03:17 +08:00
        1
    happypy1   105 天前
    @SpringBootApplication(scanBasePackages = "co.yiiu.pybbs")

    你把你的那个 jar 里的包也加进去试试看?
        2
    visaxin906   105 天前
    spring context -> read xml -> scan bean
        3
    tomoya92   105 天前
    @happypy1 #1 jar 中的包名跟 pybbs 的包名一样,帖子内容中有说明,就是扫不到。。
        4
    tomoya92   105 天前
    @visaxin906 #2 你的意思是在 jar 包中写一个 xml 来声明 jar 包中的 bean,然后在 pybbs 里通过
        5
    tomoya92   105 天前
    @tomoya92 #4 你的意思是在 jar 包中写一个 xml 来声明 jar 包中的 bean,然后在 pybbs 里通过 applicationContext 来读取 jar 包中的 xml 配置文件从而达到加载 jar 包中的 bean 的目的吗?
        6
    br00k   105 天前
    你应该使用 starter 组件开发。在组件 spring.factories 的配置里指定配置文件,在配置文件里注解设置包扫描路径。
        7
    c4f36e5766583218   105 天前
    1. 使用包扫描扫到那个 bean (如果这个 bean 有扫描注解)
    2. xml 配置
    3. java 配置
        8
    limuyan44   105 天前 via Android
    按 spring 方式正常引就好了,不是入门的基础吗。
        9
    MoHen9   105 天前 via Android
    如果普通方式运行是正常的,那就是打包的原因了,真的将依赖和配置打包进去的话,不应该出现扫描不到的问题,建议用解压软件看看打的 jar 结构,从来没用过 mvn assembly 这种命令打包,一般不是用 mvn build 打包吗?
        10
    Leiothrix   105 天前
    老哥,
        11
    Leiothrix   105 天前
    老哥,你新建的那个 maven 项目也有 Spring Boot 的依赖吗?如果有依赖且存在启动类的话是不可以直接打成 jar 包作为依赖的哦,这是一个陷阱。可执行 Spring Boot 项目打出来的默认 jar 包不可以作为依赖。你可以去查阅一下相关材料,然后最好建一个普通的 maven 项目去放置通用的 common 类。
        12
    tomoya92   104 天前
    @Leiothrix #11 新建的那个项目就是个普通的 maven 项目,没有 springboot 依赖
        13
    tomoya92   104 天前
    @br00k #6 一样的吧,starter 不是也要打包后然后配置在 springboot 主项目里吗?

    难道 staretr 开发好之后,放在 lib 目录中就可以默认加载了?
        14
    tomoya92   104 天前
    @MoHen9 #9 貌似找到原因了,在主项目里打包后,生成的 jar 包里有个 MANIFEST.MF 文件,里面定义了 Class-Path: xxx.jar 所有依赖的 jar 包都在这定义好了,所以项目在启动的时候才会加载这些 jar 包

    我新建的那个 maven 项目打成的 jar 包没有引入到项目的 pom 文件里,所以在打主项目的 jar 包时,这个 Class-Path 里就没有我开发的那个 jar 包,这也导致了项目启动的时候不加载它

    原因找到了,然后我就在尝试配置 maven-jar-plugin 插件,增加上了 lib/* 打包识别不了,换成 lib/*.jar 也识别不了,这个插件好像不支持通配符

    然后就只能在启动项目之后,手动去使用 spring 的一些工具类将插件里开发的类加载到 ioc 容器里了,现在还没有折腾出来。。
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1003 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 19ms · UTC 18:42 · PVG 02:42 · LAX 11:42 · JFK 14:42
    ♥ Do have faith in what you're doing.