首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

由Spring Quartz 实例化时抛出SQL Exception的有关问题来看spring的autowire(自动装配)

2013-09-11 
由Spring Quartz 实例化时抛出SQL Exception的问题来看spring的autowire(自动装配)项目使用Spring Quartz,

由Spring Quartz 实例化时抛出SQL Exception的问题来看spring的autowire(自动装配)
项目使用Spring Quartz,声明如下schedule:

<beans default-autowire="byName">...<bean id="schedulerBackend" name="code">[ERROR][2010-03-02 15:06:25,549] Context initialization failedorg.springframework.beans.factory.BeanCreationException: Error creating bean with name 'backEndService' defined in class path resource [service-appContext.xml]: Cannot resolve reference to bean 'schedulerBackend' while setting bean property 'scheduler'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schedulerBackend' defined in class path resource [service-appContext.xml]: Invocation of init method failed; nested exception is org.quartz.SchedulerConfigException: Failure occured during job recovery. [See nested exception: org.quartz.impl.jdbcjobstore.LockException: Failure obtaining db row lock: ORA-00942: table or view does not exist [See nested exception: java.sql.SQLException: ORA-00942: table or view does not exist]]at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:275)at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:104)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1210)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:978)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:462)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:404)at java.security.AccessController.doPrivileged(Native Method)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:375)... ...Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schedulerBackend' defined in class path resource [service-appContext.xml]: Invocation of init method failed; nested exception is org.quartz.SchedulerConfigException: Failure occured during job recovery. [See nested exception: org.quartz.impl.jdbcjobstore.LockException: Failure obtaining db row lock: ORA-00942: table or view does not exist [See nested exception: java.sql.SQLException: ORA-00942: table or view does not exist]]at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1302)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:463)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:404)at java.security.AccessController.doPrivileged(Native Method)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:375)... 35 moreCaused by: org.quartz.SchedulerConfigException: Failure occured during job recovery. [See nested exception: org.quartz.impl.jdbcjobstore.LockException: Failure obtaining db row lock: ORA-00942: table or view does not exist [See nested exception: java.sql.SQLException: ORA-00942: table or view does not exist]]at org.quartz.impl.jdbcjobstore.JobStoreSupport.initialize(JobStoreSupport.java:493)at org.quartz.impl.jdbcjobstore.JobStoreCMT.initialize(JobStoreCMT.java:144)... 45 more

本身定义的Quartz部分的应用根本涉及不到DB, 怎么会抛出SQL Exception呢,
查看一下出问题的源码
org.springframework.scheduling.quartz.SchedulerFactoryBean if(dataSource != null)mergedProps.put("org.quartz.jobStore.class", (org.springframework.scheduling.quartz.LocalDataSourceJobStore.class).getName());

看来异常就抛出在这个地方,但是SchedulerFactoryBean的dataSource属性并没有指定啊,为什么不为空呢?
上网搜了一下,原来问题出在Spring配置文件的autowire上。
spring提供了一个通过配置文件进行注入的很简便的功能,就是<beans default-autowire="byName">这段,翻了一下Spring的官方文档,autowire可以配置5个值:

no -- (Default) No autowiring. Bean references must be defined via a ref element. Changing the default setting is not recommended for larger deployments, because specifying collaborators explicitly gives greater control and clarity. To some extent, it documents the structure of a system.
默认值,不自动装配,给Bean注入属性必须通过<ref />标签,基于较大的spring配置文件,推荐使用这个默认值而不是其他的值,对每一个bean的注入都单独指定,这样比较清晰切易读,一个bean被注入了哪些属性,每个属性都注入的是什么值 都明确指定,一定程度上体现了一个系统的层次结构。


byName -- Autowiring by property name. Spring looks for a bean with the same name as the property that needs to be autowired.
按照属性的名称装配,spring根据bean的属性名自动在指定范围内搜索,如果找到名称匹配的的bean描述,就自动注入给定义的bean。而之前启动quartz失败,也正是因为spring的配置文件指定了default-autowire="byName",而项目中其他部分用的datasource正好命名成通用的“dataSource”,这样spring就“自作聪明”把项目里用的dataSource也注入给了本不想要它的SchedulerFactoryBean。


byType -- Allows a property to be autowired if exactly one bean of the property type exists in the container. If more than one exists, a fatal exception is thrown, which indicates that you may not use byType autowiring for that bean. If there are no matching beans, nothing happens; the property is not set. If this is not desirable, setting the dependency-check="objects" attribute value specifies that an error should be thrown in this case.
按照类型装配,按照文档的描述,还是不用它为妙,举例:一个bean1有一个属性是A类型的,而上下文中有一个bean2是A类型的,这样spring就自动把bean2的实例赋值给bean1的这个属性。当上下文中有多个A类型的bean时,这个配置会导致抛出致命异常,而那个A类型的属性也不会set值。


constructor -- Analogous to byType, but applies to constructor arguments. If there is not exactly one bean of the constructor argument type in the container, a fatal error is raised.
byType的一个变通,只是把byType情况的属性替换为构造函数的参数。相当于上例中的这个bean1的属性改成bean1的构造方法的一个参数。spring把相同类型的bean赋值给这个参数。同类型的参数多于一个时也会抛出致命异常


autodetect -- Chooses constructor or byType through introspection of the bean class. If a default constructor is found, the byType mode is applied.
自动指定,按照类型和按照构造器的一个折衷,如果bean1有默认构造器(无参),则按照byType处理,否则,按照constructor处理。


理解了上面的描述,再回头来看这个问题,解决方案就明朗了:
方法一:去掉default-autowire="byName"配置,也就是用默认配置,这样spring就不会隐式的注入值给属性
方法二:如果想保留byName配置,可以显式的注入null给bean,这样spring也不会把不期望的值再注入给属性,比如上面的配置文件可以改成如下
<beans default-autowire="byName">...<bean id="schedulerBackend" name="code"><beans default-autowire="byName">...<bean id="schedulerBackend" autowire-candidate="false" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">   <property name="schedulerName"><value>quartz_backend</value></property>    <property name="triggers"><list><!-- 自定义Cron trigger bean --><ref local="Customer_CronTriggerBean"/>      </list>    </property></bean></beans>

我的异常网推荐解决方案:org.springframework.beans.factory.BeanCreationException:,http://www.myexception.cn/j2ee/10759.html

热点排行