如何在多线程中注入bean?! 财富值50

2016-10-14 20:49发布

前几天,在sf这里也提过这个问题,但是仍未得到解决,上一个问题是这个在Service中注入Dao不成功,Dao为null。但根据大虾们的回答,我想再理顺一下这个项目的逻辑,免得各位看着都不懂我在说什么。本人是spring小白,整个项目环境搭建是前辈写下的,我只是根据他的方法来添加修改,所以有很多框架上的逻辑我并不是看得很懂。

我想实现的是——用多线程通过socket不断获取从客户端发送过来的消息,并对消息联系JDBC进行分析

P.S.代码部分都只截取了重要的部分
我先放一下其中一个service和dao的实现:

1)ConcentratorService:

public interface ConcentratorService {     public List<Concentrator> getConcentratorListByMacAddresses(String[] macAddr) throws Exception; }

2)ConcentratorServiceImpl:

@Service("ConcentratorService") public class ConcentratorServiceImpl implements ConcentratorService{     @Autowired     ConcentratorDao concentratorDao;     public Concentrator findConcentratorByCaddress(String caddress) throws Exception{             // TODO Auto-generated method stub             return concentratorDao.findConcentratorByCaddress(caddress);     } }

3)ConcentratorDao

public interface ConcentratorDao {     public List<Concentrator> getConcentratorListByMacAddresses(String[] macAddr) throws Exception; }

4)ConcentratorDaoImpl

public class ConcentratorDaoImpl implements ConcentratorDao {      @Autowired     SessionFactory sessionFactory;      Session session = null;     Transaction tx = null;          public void setSessionFactory(SessionFactory sessionFactory) {         this.sessionFactory=sessionFactory;     }          @Override     public List<Concentrator> getConcentratorListByMacAddresses(String[] macAddr) throws Exception {         session = sessionFactory.openSession();         tx = session.beginTransaction();                  StringBuffer sb = new StringBuffer("from Concentrator where caddress in (");         for(int i=0; i<macAddr.length; i++){             if(i==macAddr.length-1){                 sb.append("?)");             }else{                 sb.append("?,");             }         }                  Query query=session.createQuery(sb.toString());         for(int i=0; i<macAddr.length; i++){             query.setParameter(i, macAddr[i]);         }                   @SuppressWarnings("unchecked")         List<Concentrator> clist=query.list();         tx.commit();         session.close();         return clist;     }      }

这里再放一下datasource.xml,这个xml是用来配置bean的。

<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:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"     xsi:schemaLocation="http://www.springframework.org/schema/mvc      http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd   http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans-4.2.xsd   http://www.springframework.org/schema/util    http://www.springframework.org/schema/util/spring-util-3.2.xsd   http://www.springframework.org/schema/context    http://www.springframework.org/schema/context/spring-context-4.2.xsd">      <bean id="dataSource"         class="org.springframework.jdbc.datasource.DriverManagerDataSource">         <property name="driverClassName" value="com.mysql.jdbc.Driver" />         <property name="url" value="jdbc:mysql://localhost:3306/gwsl?characterEncoding=gbk" />  <!-- ?characterEncoding=UTF-8&amp;useOldAliasMetadataBehavior=true" -->         <property name="username" value="XXX" />         <property name="password" value=" XXX" />     </bean>     <bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">         <property name="sessionFactory" ref="sessionFactory"></property>     </bean>     <bean id="sessionFactory"         class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">         <property name="dataSource" ref="dataSource" />         <property name="annotatedClasses">             <list>                 <value>com.streetLight.model.Concentrator</value>             </list>         </property>         <property name="hibernateProperties">             <props>                 <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>                 <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>             </props>         </property>     </bean>          <bean id="txManager"         class="org.springframework.orm.hibernate4.HibernateTransactionManager">         <property name="sessionFactory" ref="sessionFactory" />     </bean>          <bean id="persistenceExceptionTranslationPostProcessor"         class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" /> <bean id="concentratorDao" class="com.streetLight.dao.ConcentratorDaoImpl"></bean>     <bean id="concentratorService" class="com.streetLight.services.ConcentratorServiceImpl"></bean>  </beans>

以防万一把web.xml也放一下:

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">   <display-name></display-name>      <session-config>   <session-timeout>30</session-timeout>  </session-config>       <context-param>     <param-name>contextConfigLocation</param-name>     <param-value>/WEB-INF/config/root-context.xml</param-value>     </context-param>     <listener>     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>     </listener>      <filter>     <filter-name>characterEncodingFilter</filter-name>     <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>     <init-param>       <param-name>encoding</param-name>       <param-value>UTF-8</param-value>     </init-param>     <init-param>       <param-name>forceEncoding</param-name>       <param-value>true</param-value>     </init-param>   </filter>   <filter-mapping>     <filter-name>characterEncodingFilter</filter-name>     <url-pattern>/*</url-pattern>   </filter-mapping>      <servlet>     <servlet-name>mvc-dispatcher</servlet-name>     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>     <init-param>       <param-name>contextConfigLocation</param-name>       <param-value>/WEB-INF/config/root-context.xml</param-value>     </init-param>     <load-on-startup>1</load-on-startup>   </servlet>   <servlet-mapping>     <servlet-name>mvc-dispatcher</servlet-name>     <url-pattern>/rest/*</url-pattern>   </servlet-mapping>      </web-app>

****这里之后就是想添加的功能的代码:****
RunSocket:

//@Component public class RunSocket {          public static void main(String[] args) throws InterruptedException {          System.out.println("开始启动websocket");          WebSocketImpl.DEBUG = false;          int port = 8888; // 端口随便设置,只要不跟现有端口重复就可以          WebSocket s = null;          try {              s = new WebSocket(port);          } catch (UnknownHostException e) {              System.out.println("启动websocket失败!");              e.printStackTrace();          }     s.start();      System.out.println("启动websocket成功!");           System.out.println("开始启动ServerSocket");      ReceiveThread mReceiveThread = new ReceiveThread();     mReceiveThread.init();     mReceiveThread.start();     } //    代码修改自: //    作者: 手插口袋_  //    链接:http://www.imooc.com/article/12401 }

下面是thread和解析信息的代码:
ReceiveThread:(方案一)

public class ReceiveThread extends Thread {          private ApplicationContext ctx;     private SpringContextUtil scu;          static final int SOCKET_PORT_0 = 8800; // 端口号     static ServerSocket mServerTest = null;     static Socket mSocket = null;     static InputStream mInput = null;     byte[] buffer;     static final byte CONTROLLER_FAULT = (byte)0x90;      List<Area> alist=new ArrayList<Area>();     List<String> msgList=new ArrayList<String>();          ConcentratorService concentratorService;          public void init() {         buffer = new byte[65536];         //scu = new SpringContextUtil();         ctx = new FileSystemXmlApplicationContext("/WebRoot/WEB-INF/config/datasource.xml");         concentratorService =(ConcentratorService) ctx.getBean("concentratorService"); //        scu.setApplicationContext(ctx); //        controllerofService =(ControllerofService) SpringContextUtil.getBean("controllerofService"); //        concentratorService =(ConcentratorService) SpringContextUtil.getBean("concentratorService"); //        lightPoleService =(LightPoleService) SpringContextUtil.getBean("lightPoleService"); //        controllerFaultService = (ControllerFaultService) SpringContextUtil.getBean("ControllerFaultService");      }      public void run() {         try {             mServerTest = new ServerSocket(SOCKET_PORT_0);         } catch (IOException e1) {             e1.printStackTrace();         }         int size = -1;         while (true) {                          try {                 if (size < 0) {                     System.out.println("等待前置机的链接....");                     mSocket = mServerTest.accept();                     System.out.println("服务器测试程序已链接....");                 } else {                     byte[] realBuffer = new byte[size];                     System.arraycopy(buffer, 0, realBuffer, 0, size);                     System.out.print("Message from front end: ");                     msgList=parseFrontEndMsg(realBuffer,alist);                     WebSocket.getMsgFromServer(msgList);                 }                 mInput = mSocket.getInputStream();                 size = mInput.read(buffer);             } catch (IOException e) {                 e.printStackTrace();             } catch (InterruptedException e) {                 // TODO Auto-generated catch block                 e.printStackTrace();             } catch (Exception e) {                 // TODO Auto-generated catch block                 e.printStackTrace();             }         }     }          public List<String> parseFrontEndMsg(byte[] mBytes,List<Area> alist) throws Exception{         ControllerFaultService controllerFaultService=this.controllerFaultService;         byte msg_code = mBytes[1];         String macAddr="";          switch (msg_code = mBytes[1]) {             case CONTROLLER_FAULT:                 //省略代码。macAddr分析自客户端发送来的信息。                     Concentrator c=concentratorService.findConcentratorByCaddress(macAddr);                 //省略代码。                 return faultList;         }         return null;     }  }

直接运行RunSocket的main函数,用上面这种方法service能被赋值,但是dao却是空的。

之后我又试了一中,本想spring自己注入的。
ReceiveThread:(方案二)

@Component public class ReceiveThread extends Thread {          static final int SOCKET_PORT_0 = 8800; // 端口号     static ServerSocket mServerTest = null;     static Socket mSocket = null;     static InputStream mInput = null;     byte[] buffer;     static final byte CONTROLLER_FAULT = (byte)0x90;      List<Area> alist=new ArrayList<Area>();     List<String> msgList=new ArrayList<String>();          @Autowired     ConcentratorService concentratorService;     //@Autowired和@Resource的运行结果都一样,concentratorService为null          public void init() {         buffer = new byte[65536];     }  //以下代码同上,省略。

但是这种方法,更是什么都没有被注入,service的值为空,我不知道问题出在哪里。
是不是spring的环境在运行RunSocket的mian函数时并没有被布置?

重申一次,service和dao的配置上应该是没什么问题的,因为在Run On Server后,controller中bean都是能成功被注入并被使用。

我在看spring的入门教程,发现和我这个工程有点差别,前辈写的接口并没有setter注入或者constructor注入,但却能运行,我猜是不是用了@Autowired这些标示就可以省略前面两种方式的注入?(如果我的问题很白痴,请不要介意啊),再此先谢过各位。

“对于我这种逻辑白痴来说,spring真的很难学。”

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
2条回答

dao实现好像没有托管给spring管理 可以通过一个在类上注解@Repository

你这个线程类是new出来的,所以Spring是没办法进行管理的。
如果要在Spring中使用多线程,建议你看下Spring的TaskExecutor