有时我们使用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容器后才能用。