一尘不染

在ZKoss控制器中可以自动接线Spring bean吗?

spring-mvc

我试图使用建议,并将这些注释放在zkoss控制器中,但是即使使用这些代码,spring服务也没有初始化,并且我得到了NullPointer。我的代码。

@VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class)
public class UserNotesListController extends SelectorComposer<Component> {
private static final long serialVersionUID = 1L;
private static final Logger log = 
LoggerFactory.getLogger(UserNotesListController.class);

@WireVariable
private UserService userService;
@WireVariable
private NoteService noteService;

private ListModel<Note> notesListModel;

@Wire
private Window window;

public UserNotesListController() {
    notesListModel = new ListModelList<>(noteService.listNotes());
    ((ListModelList<Note>) notesListModel).setMultiple(true);
    log.info("Конструктор класса {} успешно создан", UserNotesListController.class.getSimpleName());
}

public ListModel<Note> getNotesListModel() {
    return notesListModel;
}

@Listen("onSelect = notesListBox")
public void updateRow() {
    Set<Note> selectedNotes = ((ListModelList<Note>) notesListModel).getSelection();
    int size = selectedNotes.size();

    showNotify(size > 0 ? size + " notes selected: " + selectedNotes : "no notes selected", window);
}

private void showNotify(String message, Component reference) {
    Clients.showNotification(message, "Info", reference, "top_right", 2000, true);
}

}

java.lang.NullPointerException
ru.mightynoobs.springhibernate.controller.UserNotesListController.<init>(UserNotesListController.java:44)
sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
java.lang.reflect.Constructor.newInstance(Constructor.java:423)
java.lang.Class.newInstance(Class.java:442)
org.zkoss.zk.ui.impl.AbstractUiFactory.newComposer(AbstractUiFactory.java:130)
org.zkoss.zk.ui.impl.AbstractUiFactory.newComposer(AbstractUiFactory.java:142)
org.zkoss.zk.ui.impl.Utils.newComposer(Utils.java:90)
org.zkoss.zk.ui.metainfo.ComponentInfo.toComposer(ComponentInfo.java:355)
org.zkoss.zk.ui.metainfo.ComponentInfo.toComposers(ComponentInfo.java:323)
org.zkoss.zk.ui.metainfo.ComponentInfo.resolveComposer(ComponentInfo.java:310)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild0(UiEngineImpl.java:834)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild(UiEngineImpl.java:826)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreate0(UiEngineImpl.java:735)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild(UiEngineImpl.java:797)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreate0(UiEngineImpl.java:757)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreate(UiEngineImpl.java:699)
org.zkoss.zk.ui.impl.UiEngineImpl.execNewPage0(UiEngineImpl.java:442)
org.zkoss.zk.ui.impl.UiEngineImpl.execNewPage(UiEngineImpl.java:356)
org.zkoss.zk.ui.http.DHtmlLayoutServlet.process(DHtmlLayoutServlet.java:217)
org.zkoss.zk.ui.http.DHtmlLayoutServlet.doGet(DHtmlLayoutServlet.java:136)
javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
org.springframework.orm.hibernate4.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:152)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)

=======

<?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:context="http://www.springframework.org/schema/context"
   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/context 
http://www.springframework.org/schema/context/spring-context.xsd">

<context:component-scan base-package="ru.mightynoobs.springhibernate"/>

<!--Database information-->
<bean id="originalDataSource" class="org.apache.commons.dbcp.BasicDataSource"
      destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url"
              value="jdbc:mysql://localhost:3306/mightynoobsdb"/>
    <property name="username" value="root"/>
    <property name="password" value="admin"/>
</bean>
<!--for log4JDBC-->
<bean id="dataSource" class="net.sf.log4jdbc.Log4jdbcProxyDataSource" >
    <constructor-arg ref="originalDataSource" />
    <property name="logFormatter">
        <bean class="net.sf.log4jdbc.tools.Log4JdbcCustomFormatter" >
            <property name="loggingType" value="SINGLE_LINE" />
            <!--<property name="margin" value="19" />--> <!-- на этой строчке Spring выдает ошибку - не может прочитать значение value -->
            <property name="sqlPrefix" value="SQL:::" />
        </bean>
    </property>
</bean>

<!--Hibernate 4 SessionFactory Bean definition-->
<bean id="sessionFactory"
      class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="annotatedClasses">
        <list>
            <value>ru.mightynoobs.springhibernate.model.user.User</value>
            <value>ru.mightynoobs.springhibernate.model.user.Role</value>
            <value>ru.mightynoobs.springhibernate.model.note.NoteState</value>
            <value>ru.mightynoobs.springhibernate.model.note.NoteType</value>
            <value>ru.mightynoobs.springhibernate.model.note.Note</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.connection.url">jdbc:mysql://localhost:3306/mightynoobsdb</prop>
            <prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
        </props>
    </property>
</bean>

<!--UserDao and UserService beans-->
<bean id="userDao" class="ru.mightynoobs.springhibernate.dao.user.UserDaoImpl">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="userService" class="ru.mightynoobs.springhibernate.service.user.UserServiceImpl">
    <property name="userDao" ref="userDao"/>
</bean>

<!--NoteDao and NoteService beans-->
<bean id="noteDao" class="ru.mightynoobs.springhibernate.dao.note.NoteDaoImpl">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="noteService" class="ru.mightynoobs.springhibernate.service.note.NoteServiceImpl">
    <property name="noteDao" ref="noteDao"/>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>

当我做这样的事情:

private UserService userService = (UserService) SpringUtil.getBean("userService")

很容易。有什么建议吗?


阅读 300

收藏
2020-06-01

共1个答案

一尘不染

我们使用普通的@Inject批注,但是我们需要对此AbstractVM进行扩展才能使其正常工作:

public abstract class AbstractVM {

    public AbstractVM() {
        this.autowire(this);
    }

    protected final void autowire(Object object) {
        this.getApplicationContext().getAutowireCapableBeanFactory()
                .autowireBean(object);
        this.getApplicationContext().getAutowireCapableBeanFactory()
                .initializeBean(object, null);
    }

    /**
     * Gets the application context.
     *
     * @return the application context
     */
    protected final ApplicationContext getApplicationContext() {
        return WebApplicationContextUtils
                .getRequiredWebApplicationContext(Executions.getCurrent()
                        .getDesktop().getWebApp().getServletContext());
    }
}

所以是vm的示例:

import javax.inject.Inject;
public class OverviewVM extends AbstractVM {

    @Inject
    private NotaService notaService;
    @Inject
    private ContactService contactService;

编辑:

@Dunni的评论是正确的。
您不能在构造函数中使用自动装配的Bean。我以前的解决方案是MVVM,但是对于MVC,您需要将该代码放置在doBeforeComposedoAfterCompose方法中而不是在构造函数中。(从中覆盖SelectorComposer

2020-06-01