java 春天:BeanCreationException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16724127/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring: BeanCreationException
提问by Mr. Polywhirl
I am trying to get the session from the session factory to use with my CRUD methods. I tried to set the session in the constructor, but the bean has not been initialized by then. How do I initialize it after the bean is created?
我正在尝试从会话工厂获取会话以与我的 CRUD 方法一起使用。我试图在构造函数中设置会话,但此时 bean 尚未初始化。创建 bean 后如何对其进行初始化?
Stacktrace
堆栈跟踪
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDaoImpl' defined in file [/home/ryan/workspace/com-byteslounge-spring-tx/target/classes/com/byteslounge/spring/tx/dao/impl/UserDaoImpl.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.byteslounge.spring.tx.dao.impl.UserDaoImpl]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1011)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:957)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:490)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.byteslounge.spring.tx.Main.main(Main.java:19)
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.byteslounge.spring.tx.dao.impl.UserDaoImpl]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1004)
... 13 more
Caused by: java.lang.NullPointerException
at com.byteslounge.spring.tx.dao.impl.UserDaoImpl.<init>(UserDaoImpl.java:24)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148)
... 15 more
UserDaoImpl.java
UserDaoImpl.java
package com.byteslounge.spring.tx.dao.impl;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.byteslounge.spring.tx.dao.UserDao;
import com.byteslounge.spring.tx.domain.User;
@Service
public class UserDaoImpl implements UserDao {
@Autowired
private SessionFactory sessionFactory;
private Session session;
public UserDaoImpl() {
session = sessionFactory.getCurrentSession();
}
public SessionFactory getSessionFactory() {
return this.sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void insertUser(User user) {
session.save(user);
}
public void removeUserByName(String username) {
User user = null;
try {
getUser(username);
} catch (IndexOutOfBoundsException e) {
System.out.println(username + " does not exist!");
} finally {
if (user != null)
session.delete(user);
}
}
public User getUserById(int userId) {
return (User) session.get(User.class, userId);
}
public User getUser(String username) {
// Query query = sessionFactory.getCurrentSession().createQuery("from User where username = :username");
// query.setParameter("username", username);
Query query = session.getNamedQuery(User.FIND_USER_BY_USERNAME).setString("username", username);
return (User) query.list().get(0);
}
@SuppressWarnings("unchecked")
public List<User> getUsers() {
Criteria criteria = session.createCriteria(User.class);
return criteria.list();
}
}
applicationContext.xml
应用上下文.xml
<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<tx:annotation-driven />
<context:component-scan base-package="com.byteslounge.spring.tx.dao.impl" />
<context:component-scan base-package="com.byteslounge.spring.tx.user.impl" />
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>database.properties</value>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="packagesToScan" value="com.byteslounge.spring.tx.domain" />
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory">
</bean>
</beans>
回答by Caesar Ralf
Use the @PostConstruct
tag and get the session then. Your beans will only be injected after your UserDaoImpl
is created and @PostConstruct
method will only be called by Spring after all your beans are injected.
使用@PostConstruct
标签然后获取会话。您的 bean 只会在您UserDaoImpl
创建之后被注入,并且@PostConstruct
方法只会在您的所有 bean 被注入后被 Spring 调用。
@Service
public class UserDaoImpl implements UserDao {
@Autowired
private SessionFactory sessionFactory;
private Session session;
public UserDaoImpl() {
}
@PostConstruct
public void init() {
this.session = sessionFactory.getCurrentSession();
}
...
}
Another way (better in my opnion) is inject by constructor and getting the current session only when you need it.
另一种方法(在我的选项中更好)是通过构造函数注入并仅在需要时获取当前会话。
...
private final SessionFactory sessionFactory;
@Autowired
public UserDaoImpl(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
private Session currentSession() {
return this.sessionFactory.getCurrentSession();
}
EDIT:Use the second way preferably, because if you get the session only after construct, calls to your DAO won't work once that session is expired. Always use SessionFactory#getCurrentSession()
when starting make calls at your transactional methods.
编辑:最好使用第二种方式,因为如果您仅在构造后获取会话,则一旦该会话过期,对 DAO 的调用将无法工作。SessionFactory#getCurrentSession()
在您的事务方法开始进行调用时始终使用。
回答by Steve Oh
As Ralf points out, the constructor is executed too early and Spring did not inject anything at this point.
正如 Ralf 指出的那样,构造函数执行得太早,此时 Spring 没有注入任何内容。
Further, you may not hold a reference to Sessionas it relies on the SessionContext mechanism, which in turn may be thread bound or servlet request bound. Your bean may has a wider scope (e.g. singleton) and you will permanently store the session from the first caller or something!
此外,您可能不会持有对Session的引用,因为它依赖于 SessionContext 机制,而后者又可能是线程绑定或 servlet 请求绑定的。您的 bean 可能具有更广泛的范围(例如单例),您将永久存储来自第一个调用者或其他东西的会话!
I suggest to always get the session from sessionFactory when needed inside the bean.
我建议在 bean 内部需要时总是从 sessionFactory 获取会话。