有时我们使用spring的注入的时候不成功,如我们在一个地方实例化一个类,这个类里面就用到依赖注入的方式,我们也在spring配置文件里写好了让它去扫描这个包,将该类纳入spring容器管理,但当我们实例化它的时候,它里面的spring的bean并没有注入,这是为什么,因为我们虽然将这个类纳入spring容器管理,但是当我们实例这个类时,这个是我们自己实例化的对象,它不属于spring管理范围,也就是不是由spring实例化的,所以它里面用到的spring的注入是不成功的。我这个是在使用phprpc里发布一个服务器,遇到的问题,发布如下:

 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page import="org.phprpc.*" %> 
<%@ page import="org.edu.scut.lab24.project.service.impl.RemoteServiceImpl" %>
<%@ page import="org.edu.scut.lab24.project.service.IRemoteService" %> 


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    
    <title>PHPRPC</title>
	
  </head>
  
  <body>
	<%  
	
	//这里必须使用接口定义
	IRemoteService remoteService = new RemoteServiceImpl();
	//实例化phprpc服务
	PHPRPC_Server phprpc_server = new PHPRPC_Server();

	//在这里把RemoteServiceImpl发布出来
	phprpc_server.add(remoteService);
	
	phprpc_server.start(request, response);
	%>  
  </body>
</html>

 

这个实例化就是自己的实例化,不是spring并不纳入spring管理范围,所以在RemoteServiceImpl里用到spring注解里是不能注入成功的,解决的办法,自己手动加载spring配置文件,

也就是再实例化一个spring容器,然后从容器里获取bean,如下:

 

1 可先建一个spring容器实例化的类,这样当你想在自己想使用spring容器的时候就用这同一个(这里以静态变量的形式存在),而不用每次都实例化一个新的spring容器,这样才不会过度消耗内容资源。

 

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 初如化spring上下文环境,初始化xml文件
 * @author Administrator
 *
 */
public class AppContext {
	
	private static AppContext instance;
	private String[] PATH = {"classpath:applicationContext.xml"};

	private AbstractApplicationContext applicationContext;
	
	public synchronized static AppContext getInstance(){
		if(instance == null)
			instance = new AppContext();
		return instance;
	}
	
	public AppContext(){
		this.applicationContext = new ClassPathXmlApplicationContext(PATH);
	}
	
	public AbstractApplicationContext getAbstractApplicationContext(){
		return this.applicationContext;
	}
}

 

 

当你在如上面的例子里的RemoteServiceImpl类用到注入,假设如下

 

@Resource
	private  IFileService fileServiceImpl;

 

那你就可以用下面的方式来获得注入的bean(在构造函数或你想用的地方):

 

if(fileServiceImpl == null)
			fileServiceImpl = (FileServiceImpl)AppContext.getInstance().getAbstractApplicationContext().getBean("fileServiceImpl");

 

 你可能会问,不什么不将fileServiceImpl直接用new FileServiceImpl 方式来实现,因为当FileServiceImpl

里面又用到注解,并用到spring对数据库的操作,所以这里只能用spring提供的bean来实例化它,即让它们处于spring容器的管理下。

 

你可能还会问你用struts里它跳到action类去,你也不没有实例化它,它里面用到的spring注解怎么又可以用呢?因为在web.xml里面就配置了spring监听web的请求,应该是将请求处理的action纳入spring容器去管理,我的web.xml配置如下:

 


<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <welcome-file-list> <welcome-file>upload.jsp</welcome-file> </welcome-file-list> <!--########### 初始化日志系统 ##################--> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>/WEB-INF/classes/log4j.properties</param-value> </context-param> <!--########## Spring默认刷新Log4j配置文件的间隔,单位为millisecond #########--> <context-param> <param-name>log4jRefreshInterval</param-name> <param-value>60000</param-value> </context-param> <!--########### 初始化Spring上下文 ##################--> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:applicationContext.xml </param-value> </context-param> <!--Spring log4j Config loader--> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> <!--Spring ApplicationContext 载入 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>

 

所以我们的请求跳到action类去处理时,在action类里的注解是可以注入的。

 

而当我在web.xml配置一个servlet,而在客户端(我使用jquery uploadify组件)请求就指定用该servlet来处理,而当这个servlet里面用到spring注解的时候,它会在客户请求时发生异常,出现如下异常:

 

严重: Allocate exception for servlet uploadServlet
javax.naming.NameNotFoundException: Name org.lab24.file.servlet.UploadServlet is not bound in this Context
	at org.apache.naming.NamingContext.lookup(NamingContext.java:770)
	at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
	at org.apache.catalina.util.DefaultAnnotationProcessor.lookupFieldResource(DefaultAnnotationProcessor.java:278)
	at org.apache.catalina.util.DefaultAnnotationProcessor.processAnnotations(DefaultAnnotationProcessor.java:187)
	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1120)
	at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:809)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:129)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
	at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:861)
	at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:579)
	at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1584)
	at java.lang.Thread.run(Unknown Source)


 开始我以有是我的web.xml没配置好,老是说servlet不能在邦定,其它是这个servlet里面的的注解不能邦定,所在这里要想用spring注解,可以用上面的方式来自己加载spring容器,或都可以在web.xml里配置使用请求的servlet处理bean也交给spring管理,这个我就不会配置,知道的网友希望告诉一下我。

 

最后总结一下:

1 当你使用直接实倒化一个类(里面用到spring的注解)时,是不没有交给spring容器管理的,除了你自己在类里面加载spring容器。


2 处理用户的请求类,只有在web.xml里配置了交由spring管理的,才能使用spring的注解,不然只能手动实例化spring容器后才能用。