问题:在filter和interceptor中经常需要调用Spring的bean,filter也是配置在web.xml中的,请问一下这样调用的话,filter中调用Spring的某个bean,这个bean一定存在吗?现在总是担心filter调用bean的时候,bean还没被实例化?
答案:因为spring bean、filter、interceptor加载顺序与它们在 web.xml 文件中的先后顺序无关。即不会因为 filter 写在 listener 的前面而会先加载 filter。最终得出的结论是: ServletContext -> listener -> filter -> servlet
由于spring bean的初始化是在listener中声明的,因此filter时,spring bean已经实例。
注入bean方法:
一、自定义一个工具类,在工具类中通过ApplicationContext获取bean
自定义一个工具类,实现自ApplicationContextAware接口,接口的方法是setApplicationContext,我们实现它,并让其为我们服务,因为Spring在load自己的时候会将上下文环境填充进来。我们所要做的就是将得到的ApplicationContext保存下来用。
@Component public class SpringUtil implements ApplicationContextAware { private static Logger log = LoggerFactory.getLogger(SpringUtil.class); /** * 当前IOC */ private static ApplicationContext applicationContext; /* * @param arg0 * * @throws BeansException * * @see * org.springframework.context.ApplicationContextAware#setApplicationContext * (org.springframework.context.ApplicationContext) */ @Override public void setApplicationContext(ApplicationContext arg0) throws BeansException { log.info("====================arg0:"+arg0); applicationContext = arg0; } public static <T>T getBean(String id,Class<T> type){ return applicationContext.getBean(id,type); } }
需要注意的是该工具类需要纳入spring的bean管理(注解:增加扫描配置component-scan或bean.xml中配置)哟,否则applicationContext 将会是空的。
二、自定义一个工具类,在工具类中通过BeanFactory 获取bean
自定义一个工具类,实现自BeanFactoryAware 接口,接口的方法是setBeanFactory,我们实现它,并让其为我们服务,因为Spring在load自己的时候会将上下文环境填充进来。我们所要做的就是将得到的BeanFactory 保存下来用。
@Component
public class BeanHelper implements BeanFactoryAware { private static BeanFactory beanFactory; @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } public static <T>T getBean(String id,Class<T> type){ return beanFactory.getBean(id,type); } }
同样,需要注意的是该工具类需要纳入spring的bean管理(注解:增加扫描配置component-scan或bean.xml中配置)哟,否则applicationContext 将会是空的。
二、使用了注解和静态化的方式来产生SpringFactory对象
上文的方法有个麻烦的地方:需要配置。而Spring2.5及之后的版本实际上加入了注解的方式进行依赖项的注入,使用如下代码也许更好:
public class SpringWiredBean extends SpringBeanAutowiringSupport { /** * 自动装配注解会让Spring通过类型匹配为beanFactory注入示例 */ @Autowired private BeanFactory beanFactory; private SpringWiredBean() { } private static SpringWiredBean instance; static { // 静态块,初始化实例 instance = new SpringWiredBean(); } /** * 实例方法 使用的时候先通过getInstance方法获取实例 * * @param beanId * @return */ public <T>T getBean(String id,Class<T> type){ return beanFactory.getBean(id,type); } public static SpringWiredBean getInstance() { return instance; } }
但是要增加一个扫描,让spring能知道注解:
<context:component-scan base-package="org.ahe"></context:component-scan>
servlet中注入bean的方法
步骤:
1 配置spring文件
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource" /> </bean>
2 在web.xml中加载spring的配置文件
<context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath*:/spring/applicationContext_*.xml </param-value> </context-param>
3 在servlet中获取名字为jdbcTemplat的bean.
public class UserAuthorizationFilter extends HttpServlet { private WebApplicationContext wac; public void init(){ //方法一: wac =WebApplicationContextUtils.getRequiredWebApplicationContext( this.getServletContext()); //方法二: wac = WebApplicationContextUtils.getWebApplicationContext( this.getServletContext()); //方法一和方法二得到的结果是一样的。 //wac的类型: org.springframework.web.context.support.XmlWebApplicationContext } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { JdbcTemplate jdbcTemplate = (JdbcTemplate)wac.getBean("jdbcTemplate"); String sql="select count(*) from customer where name='liwj' and password='1111111'"; int num=jdbcTemplate.queryForInt(sql); if(num==1){ System.out.println("has"); }else{ System.out.println("hasnot"); } }