java - 在 ApplicationContext 中找到 Bean,但在尝试 Autowiring 时找不到

标签 java xml spring spring-batch

我有一个 Spring JobLauncher 实现,我正在尝试 Autowiring 到 @Component 类中,假设它称为 SimpleComponent。这个名为 SomeJobLauncher 的作业启动器正在通过 bean 定义加载到 Spring 上下文中。

如果我在 Spring 应用程序上下文中 Autowiring 到 SimpleComponent 中,并尝试通过 getBean("someLauncher") 获取 bean,我将获取我的 bean,然后没有问题。

然而,尽管确认 bean 已 100% 加载到 ApplicationContext 中,但当我尝试将 someLauncher Autowiring 到 SimpleComponent 中时,我收到此错误:

No matching bean of type [com.somepackage.SomeJobLauncher] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

这里有几个相关的类。由于此应用程序的巨大规模,我无法展示每个单独的 xml 配置文件/Java 类,但如果您希望看到一些特定的内容,我愿意接受请求。

那么有人知道这是怎么可能的吗?

public class SomeJobLauncher extends BatchScheduleJobLauncher {

    private static final long serialVersionUID = 89457928374294789723L;
    /**
     * Spring inject the appropriate Server name from the Batch properties file.
     */
    @Value("${dataload.schedule.server}")
    private String jobSchedulerServer;


    /**
     * No-argument constructor.
     */
    public SomeJobLauncher() {
    }



    @Override
    protected String supplyScheduleServer() {
        return this.jobobSchedulerServer;
    }

}

父类:

public abstract class BatchScheduleJobLauncher extends SimpleJobLauncher implements Serializable {

    private static final long serialVersionUID = -1138294811959957159L;

    private String batchJobIdentifier = "not set";
    /**
     * Set by Spring property setting from the specific JobConfig.xml file inside the
     * WEB project.
     */
    private Job job;
    /**
     * Set by Spring property setting from the specific JobConfig.xml file inside the
     * WEB project.
     */
    private JobLauncher jobLauncher;
    /**
     * Set by Spring injection from within the descendent's implementation of the supplyScheduleServer
     * method.
     */
    private String jobSchedulerServer;


    /**
     * No argument constructor
     * Default Constructor
     */
    public BatchScheduleJobLauncher() {
    }


    /**
     * Spring invoked method.
     * 
     * @return org.springframework.batch.core.Job - Interface
     */
    public Job getJob() {
        return this.job;
    }

    /**
     * Spring invoked method.
     * 
     * @return org.springframework.batch.core.launch.JobLauncher - Interface
     */
    public JobLauncher getJobLauncher() {
        return this.jobLauncher;
    }

    /**
     * Method invoked from the corresponding Job Config XML file in the WEB
     * project or from the "Upon Demand" manual invocation process.
     * 
     * @return JobExecution - see internal "Status" for Job Completion
     *         indication.</br> Status set by this method is either
     *         BatchStatus.ABANDONED, BatchStatus.COMPLETED or
     *         BatchStatus.FAILED.
     */
    public JobExecution launch() {
        JobExecution returnValue;
        String timeParameter = "time";
        long systemTime = System.currentTimeMillis();
        JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
        JobParameters jobParameters;
        String ipAddressDefinedServer;
        ExitStatus exitStatus;

        // Build System Time Job parameter.
        jobParametersBuilder.addLong(timeParameter, systemTime);
        jobParameters = jobParametersBuilder.toJobParameters();

        this.batchJobIdentifier = supplyJobIdentifier();
        this.jobSchedulerServer = supplyScheduleServer();

        try {
            if (Util.isNullOrEmpty(this.jobSchedulerServer)) {
                LoggerUtil.error("Batch Job Scheduler Server NOT set on BatchScheduleJobLauncher ancestor class for the [" +
                                 this.batchJobIdentifier + "] Batch Load Job so 'run' could not be executed.");
                returnValue = new JobExecution(new JobInstance(new Long(0),
                                                               jobParameters, 
                                                               supplyJobIdentifier()));
                exitStatus = new ExitStatus(ExitStatus.FAILED.getExitCode());
                returnValue.setExitStatus(exitStatus);
                returnValue.setEndTime(new Date());
                returnValue.setStatus(BatchStatus.ABANDONED);
            } else {
                ipAddressDefinedServer = InetAddress.getLocalHost().getHostName();
                if (this.jobSchedulerServer.equalsIgnoreCase(ipAddressDefinedServer)) { 
                    // job scheduled server found.
                    LoggerUtil.info("Executing 'run' from inside the launch method of the BatchScheduleJobLauncher object.");
                    returnValue = this.jobLauncher.run(this.job, jobParameters);
                } else {
                    LoggerUtil.warn("Batch Job Scheduler Server ["  + this.jobSchedulerServer + 
                                    "] does NOT match the server name [" + ipAddressDefinedServer +
                                    "] found at IP Address [" + InetAddress.getLocalHost() +
                                    "] so 'run' could not be executed.");
                    returnValue = new JobExecution(new JobInstance(new Long(0),
                                                                   jobParameters, 
                                                                   supplyJobIdentifier()));
                    exitStatus = new ExitStatus(ExitStatus.FAILED.getExitCode());
                    returnValue.setExitStatus(exitStatus);
                    returnValue.setEndTime(new Date());
                    returnValue.setStatus(BatchStatus.ABANDONED);
                }
            }
        } catch (Exception e) {
            LoggerUtil.error("ERROR while running the BatchScheduleJobLauncher for the [" +
                             this.batchJobIdentifier + "] Batch Load Job. Error is [" + e.getMessage()+ "].");
            returnValue = new JobExecution(new JobInstance(new Long(0),
                                                           jobParameters, 
                                                           supplyJobIdentifier()));
            returnValue.addFailureException(e);
            returnValue.setStatus(BatchStatus.FAILED);
        }

        return returnValue;
    }

    /**
     * Called by Spring based on the property attributes in the corresponding
     * Job Config XML file.</br> Sets {@link #job}.
     * 
     * @param org.springframework.batch.core.Job - Interface
     */
    public void setJob(Job inJob) {
        this.job = inJob;
    }

    /**
     * Called by Spring based on the property attributes in the corresponding
     * Job Config XML file.</br> Sets {@link #jobLauncher}.
     * 
     * @param org.springframework.batch.core.Job - Interface
     */
    public void setJobLauncher(JobLauncher inJobLauncher) {
        this.jobLauncher = inJobLauncher;
    }

    /**
     * Must be implemented by the descendant Job Launcher job to define the type
     * of Batch job being run.</br> Sets {@link #batchJobIdentifier}.
     * 
     * @return String - the batch job type.
     */
    abstract protected String supplyJobIdentifier();

    /**
     * Must be implemented by the descendant Job Launcher job to define the
     * specific schedule Server name.</br> The appropriate value will be Spring
     * injected (see someJobLauncher.java).</br> Sets {@link #jobSchedulerServer}.
     * 
     * @return String - the scheduler server name.
     */
    abstract protected String supplyScheduleServer();
}

启动器的 Bean 定义:

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

   <tx:annotation-driven proxy-target-class="true" />

  <bean id="transactionManager"
    class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />

  <bean id="jobRepository"
    class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
    <property name="transactionManager" ref="transactionManager" />
  </bean>

  <bean id="jobLauncher" 
    class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
    <property name="jobRepository" ref="jobRepository" />
  </bean>
</beans>

作业的 Bean 定义:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:batch="http://www.springframework.org/schema/batch"
  xmlns:task="http://www.springframework.org/schema/task"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/task
    http://www.springframework.org/schema/task/spring-task-3.0.xsd
    http://www.springframework.org/schema/batch
    http://www.springframework.org/schema/batch/spring-batch-2.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <tx:annotation-driven proxy-target-class="true" />

  <!-- Multiple threading not needed so set pool size to one. -->
  <task:scheduler id="scheduler" pool-size="1" />   

  <bean id="someLoadJob" class="com.somepackage.SomeLoadJob" />

  <!-- Once Excel File is found on the Load Job landing zone the Batch Load will be run -->
  <!-- This Job Instance must always run as a new Job. -->
  <batch:job id="processLoadJob" restartable="false">
    <batch:step id="processLoadJobStep">
      <batch:tasklet ref="LoadJob" />
    </batch:step>
  </batch:job>

  <bean id="someLauncher" class="com.somepackage.SomeJobLauncher">
    <property name="jobLauncher" ref="jobLauncher"></property>
    <property name="jobRepository" ref="jobRepository"></property>
    <property name="job" ref="processLoadJob"></property>
  </bean>

  <task:scheduled-tasks scheduler="scheduler">
  <task:scheduled ref="someLauncher" method="launch" cron="${batch.scheduler.time}"/>
  </task:scheduled-tasks>

</beans>

Autowiring 类。你必须相信我的话,这个类正在扫描组件。

@Component
public class SimpleComponent {

    private Map<String, JobCategoryStatus> jobStatuses = new HashMap<String, JobCategoryStatus>();;
    private Map<String, List<JobCategoryStatus>> categoryStatuses = new HashMap<String, List<JobCategoryStatus>>();

//  public SimpleComponent() { };

    @Autowired
    private ApplicationContext ctx;

    //This autowire doesn't work
    @Autowired
    private SomeJobLauncher someLauncher;

    //This method works
    public SomeJobLauncher getSomeLauncher() {
         Object someLauncher = ctx.getBean("someLauncher");
         return someLauncher;
    }



}

最佳答案

我可能遗漏了一些东西,但我没有看到你打开组件扫描 ()。因为您没有扫描组件并且 SimpleComponent 没有在您的上下文中定义,所以我不希望 Spring Autowiring 它。一旦你为你想要的包打开组件扫描,我希望它能工作。

关于java - 在 ApplicationContext 中找到 Bean,但在尝试 Autowiring 时找不到,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21121891/

相关文章:

java - 如何使 Eclipse Java 将项目依赖项设置为解决方案项目而不是引用 JAR

c# - 如何在调用 .LoadXml() 之前检查字符串输入中的有效 xml

spring - 用 Spring 调试 Jackson

spring - 何时使用 Spring @Autowire 注解

java - Spring MVC Controller 无法直接与 Spring Web Flow 连接?

java - 向 Autodesk 进行身份验证

Java Apache POI : excel cell color

Java 脚本引擎类实例化

java - 回复 : Big XML file

java - JAXB 通过映射