当我登录我的应用程序时,我会在NullPointerException
字段@Autowired
获得hashProvider
。奇怪的是,它有时只会发生!当我尝试调试模式时,该字段是自动装配的,当我正常运行时,它不是。
@Configurable(preConstruction=true)
@Entity
@Table(name="DB_USER")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "USER_TYPE", discriminatorType = DiscriminatorType.STRING)
public abstract class User extends AbstractEntity {
//...
@Autowired(required = true)
private transient HashProvider hashProvider;
//...
public boolean hasPassword(String password){
LOG.info("is null "+(hashProvider==null)); //sometimes is null sometimes not
return hashProvider.computeHash(password + salt).equals(this.password); //null pointer
}
}
@Component("hashProvider")
public class SHA1Provider implements HashProvider{
//...
@Override
public String computeHash(String s) {
//...
}
}
另外,以不同用户身份登录会抛出异常。以Doctor
身份登录时,该字段为空,为AdminUser
,该字段不是
@Entity
public class AdminUser extends User {
@Override
public String toString() {
return super.toString() + "AdminUser{" + '}';
}
@Override
public Boolean isAdmin() {
return true;
}
}
@Entity
@DiscriminatorValue("doctor")
public class Doctor extends User {
private String address;
@Column(length = 10, unique = true, name = "DOCTOR_BCN", nullable = false)
private Long birthNumber;
private Integer phone;
@OneToMany(mappedBy = "doctor")
@OrderBy("name ASC")
private List<Patient> patients;
//setters and getters
@Override
public String toString() {
return super.toString() + "Doctor{}";
}
@Override
public Boolean isAdmin() {
return false;
}
}
这是applicationContext.xml文件:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"
>
<!-- Use annotation to configure Spring context -->
<context:annotation-config />
<mvc:annotation-driven />
<!-- Search for beans under the com.wpa package (Using annotation @Component, @Repository, @Service) -->
<context:component-scan base-package="com.wpa"/>
<!-- @Configurable support -->
<context:spring-configured/>
<!-- Property files -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/WEB-INF/properties/jdbc.properties</value>
<value>/WEB-INF/properties/jpa.properties</value>
</list>
</property>
</bean>
<!-- Connection pool -->
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- This defines the EntityManagerFactory bean, which provides the application with EntityManager instances = persistence context -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="databasePlatform" value="${jpa.platform}"/>
<property name="generateDdl" value="true"/>
<property name="showSql" value="true"/>
</bean>
</property>
<property name="jpaPropertyMap">
<map>
<entry key="eclipselink.weaving" value="static"/>
<entry key="eclipselink.ddl-generation" value="create-or-extend-tables" />
</map>
</property>
<property name="packagesToScan" value="com.wpa"/>
<property name="jtaDataSource" ref="dataSource"/>
</bean>
<!-- Transaction manager for declarative transactional demarcation -->
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- Use the declared transaction manager to manage transaction using the @Transactional annotation -->
<!-- proxy-target-class=true enables use of concrete classes without interfaces as beans with the @Transactional annotation -->
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager">
<ref bean="txManager"/>
</property>
</bean>
</beans>
答案 0 :(得分:0)
@Autowire只能用于由spring标记的类。例如@Service, @component ,@Repostitory
编辑:我错过了@Configurable,这使得它也成为了一个春天。
我知道的另一件事是,如果你在反序列化后在成员上写瞬态它将为null ..这似乎与你的情况非常相似。 这有意义吗?
编辑: 不应在JPA实体中使用Spring bean。这是不好的做法。 实现此目的的最佳实践是创建包装器,其中包含具有附加功能的pojo。我认为最好的办法就是让逻辑服务即使它是一个很小的逻辑......