自动连接Spring3.2独立应用程序失败

s6fujrry  于 2021-06-30  发布在  Java
关注(0)|答案(2)|浏览(321)

这是我第一次找不到解决stackoverflow问题的方法:
我正在尝试创建一个可执行的jar独立应用程序,它带有基于注解的自动连接,但是我无法获得runnable jar文件(作为runnable jar文件从eclipse导出)来完成它的工作。它确实可以直接从eclipse作为java应用程序运行,而不是通过控制台作为独立应用程序运行 > java -jar test.jar .

Exception in thread "main" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'handler': Injection of autowired dependen
cies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.example.serv
ice.UserService com.example.controller.TestHandler.userService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionEx
ception: No qualifying bean of type [com.example.service.UserService] found for dependency: expected at least 1 bean which qualifies as auto
wire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBe
anPostProcessor.java:288)

我试图通过遵循本博客中描述的“手动初始化自动布线”模式来避免此类问题:http://sahits.ch/blog/?p=2326 无济于事。请注意,我也在使用hibernate jpa,但没有persistence.xml(因此tx:annotation-driven/)-而且不要被我使用的两个数据库所阻碍,在eclipse中运行时,它可以正常工作。
main.java文件:

public class Main {
    @Autowired
    private TestRunner testRunner;

    public Main() {
        final ApplicationContext context = new ClassPathXmlApplicationContext("app-context.xml");
        AutowireCapableBeanFactory acbFactory = context.getAutowireCapableBeanFactory();
        acbFactory.autowireBean(this);
    }

    public static void main(String[] args) throws Exception {
        Main main = new Main();

        main.testRunner.run();
    }
}

testrunner.java文件:

@Component
public class TestRunner {
    @Autowired
    Handler handler;

    public void run() {
        handler.doTest();
    }
}

testhandler.java(稍后将设置groupid和groupname):

@Controller
public class TestHandler implements Handler {
    private static Log syslog = LogFactory.getLog(TestHandler.class);

    @Autowired
    private UserService userService;

    @Autowired
    private GroupService groupService;

    private Long groupId;
    private String groupName;

    public void doTest() {
        if (groupId != null) {
            List<User> users = userService.loadUsersByGroupId(groupId);
            syslog.debug("Amount of users found: " + users.size());
        } else {
            syslog.debug("groupId is null");
        }

        if (groupName != null) {
            List<Group> groups = groupService.loadGroupsByName(groupName);
            syslog.debug("Amount of groups found: " + groups.size());
        } else {
            syslog.debug("groupName is null");
        }

    }

    public void setGroupId(Long groupId) {
        this.groupId = groupId;
    }

    public void setGroupName(String groupName) {
        this.groupName = groupName;
    }
}

userserviceimpl.java文件:

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    UserDAO userDAO;

    @Override
    public List<User> loadUsersByGroupId(long id) {
        return userDAO.findAllByGroupId(id);
    }

...

userdaoimpl.java文件:

@Repository
@Transactional("db1")
public class UserDAOImpl implements UserDAO {

    @PersistenceContext(unitName="entityManagerDb1")
    private EntityManager em;

    @SuppressWarnings("unchecked")
    @Override
    public List<User> findAllByGroupId(long id) {
        Query query = em.createQuery("select distinct u from User u " +
                "where u.groupId = :groupId");
        query.setParameter("groupId", id);

        return query.getResultList();
    }

    ...

app-context.xml(使用注解配置的jpa,使用两个数据库):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
        "
        >

    <context:annotation-config/>

    <context:component-scan base-package="com.example"/>

    <!-- db1 -->
    <bean id="dataSourceDb1" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
      <property name="driverClass" value="com.mysql.jdbc.Driver" />
      <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/db1?characterEncoding=UTF-8" />
      <property name="user" value="root" />
      <property name="password" value="root" />
      <property name="minPoolSize" value="5" />
      <property name="maxPoolSize" value="10" />
      <property name="maxStatements" value="0" />
      <property name="preferredTestQuery" value="SELECT 1" />
      <property name="idleConnectionTestPeriod" value="600" />
    </bean>

     <bean id="entityManagerFactoryDb1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="entityManagerDb1"/>
         <property name="dataSource" ref="dataSourceDb1"/>
        <property name="packagesToScan">
            <list>
                <value>com.example.domain.db1</value>
            </list>
        </property>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="false"/>
                <property name="generateDdl" value="true"/>
                <property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
            </bean>
        </property>

        <property name="jpaProperties">
            <props>
               <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
               <prop key="hibernate.connection.show_sql">true</prop>
               <prop key="hibernate.hbm2ddl.auto">validate</prop>
               <prop key="hibernate.use_outer_join">true</prop>
               <prop key="hibernate.connection.characterEncoding">UTF-8</prop>
               <prop key="hibernate.connection.useUnicode">true</prop>
            </props>
        </property>

    </bean>

    <!-- Configure transaction manager for JPA -->
    <bean id="transactionManagerDb1" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactoryDb1"/>
        <qualifier value="db1"/>
    </bean>

    <!-- db2 -->
    <bean id="dataSourceDb2" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
      <property name="driverClass" value="com.mysql.jdbc.Driver" />
      <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/db2?characterEncoding=UTF-8" />
      <property name="user" value="root" />
      <property name="password" value="root" />
      <property name="minPoolSize" value="5" />
      <property name="maxPoolSize" value="10" />
      <property name="maxStatements" value="0" />
      <property name="preferredTestQuery" value="SELECT 1" />
      <property name="idleConnectionTestPeriod" value="600" />
    </bean>

     <bean id="entityManagerFactoryDb2" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="entityManagerDb2"/>
         <property name="dataSource" ref="dataSourceDb2"/>
        <property name="packagesToScan">
            <list>
                <value>com.example.domain.db2</value>
            </list>
        </property>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="false"/>
                <property name="generateDdl" value="true"/>
                <property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
            </bean>
        </property>

        <property name="jpaProperties">
            <props>
               <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
               <prop key="hibernate.connection.show_sql">true</prop>
               <prop key="hibernate.hbm2ddl.auto">validate</prop>
               <prop key="hibernate.use_outer_join">true</prop>
               <prop key="hibernate.connection.characterEncoding">UTF-8</prop>
               <prop key="hibernate.connection.useUnicode">true</prop>
            </props>
        </property>

    </bean>

    <bean id="transactionManagerDb2" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactoryDb2"/>
        <qualifier value="db2"/>
    </bean>

    <tx:annotation-driven />

</beans>

在eclipse中运行它就像预期的那样工作,这让我抓狂。eclipse导出特性是否有一定的局限性?对创建可运行jar文件的另一个框架有什么提示吗?

ao218c7q

ao218c7q1#

当您在eclipse中运行它时,所有spring依赖项和其他依赖项都会加载到您的类路径中,但是当您将应用程序导出为jar时,只会导出您的类,而不会导出依赖项类。
通常有两种方法可以实现一个独立的jar。您可以创建一个“uber-jar”(请参见是否可以创建一个“uber”jar,其中包含项目类和项目依赖项,并将它们作为jar与自定义清单文件一起使用?),其中所有依赖项jar都被扩展到一个jar中。但是,这种方法可能有风险,因为如果jar具有相同的文件名(例如:meta-inf中的同一配置文件),它们可能会相互覆盖
另一个更合适的方法是使用maven依赖插件(参见ependency:copy)将所有依赖项复制到“dependencies”文件夹中。然后把你的jar

java -cp "myjar.jar;dependencies/*" org.mycompany.MainClass

这不是一个真正独立的jar,而是一个独立的文件夹。缺点是每次添加/删除依赖项(例如:从maven)时,都必须对依赖项文件夹执行相同的操作

sg24os4d

sg24os4d2#

如果它是从eclipse运行的,而不是从导出的jar文件运行的,那么导出就有问题
在导出窗口中有一个复选框 Add directory entries 应该检查组件扫描是否正常

相关问题