在Spring MVC中,Controller中使用service只需使用注解@Resource/@Autowired就行,但是一般类(即不使用@Controller注解的类)要用到service时,Spring中的Service不是你想new就能new的,因为通过new实例化的对象脱离了Spring容器的管理,获取不到注解的属性值,所以会是null,就算调用service的类中有@Component注解加入了Spring容器管理,也还是null.
实例:
@Component public class Test { @Resource(name = "testServiceImpl") private SessionService testService; public Test() { } public void run() { System.out.println("****"); System.out.println(testService); } }
在Controller里 new 这个对象
Test test = new Test(); test.run();通过Debug可以得到 test为null
可用如下方法:
一、普通类与工具类共同的解决方法:
1、SpringContextUtil
package com.test.framework.utils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class SpringContextUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; // Spring应用上下文环境 // 下面的这个方法上加了@Override注解,原因是继承ApplicationContextAware接口是必须实现的方法 @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringContextUtil.applicationContext = applicationContext; } public static ApplicationContext getApplicationContext() { return applicationContext; } public static Object getBean(String name) throws BeansException { return applicationContext.getBean(name); } public static Object getBean(String name, Class requiredType) throws BeansException { return applicationContext.getBean(name, requiredType); } public static boolean containsBean(String name) { return applicationContext.containsBean(name); } public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException { return applicationContext.isSingleton(name); } public static Class getType(String name) throws NoSuchBeanDefinitionException { return applicationContext.getType(name); } public static String[] getAliases(String name) throws NoSuchBeanDefinitionException { return applicationContext.getAliases(name); } }
2、Spring的配置文件application.xml中进行如下配置
<bean id="SpringContextUtil" class="com.test.framework.utils.SpringContextUtil" scope="singleton"></bean>
3、使用
DictService dictService = (DictService) SpringContextUtil.getBean("dictService");
List<dict> dict = (List<dict>) dictService.findByHQL(hql);
二、工具类单独的解决方法
如果我们要在我们自己封装的Utils工具类中或者非controller普通类中使用@Autowired注解注入Service或者Mapper接口,直接注入是不可能的,因为Utils使用了静态的方法,我们是无法直接使用非静态接口的,当我们遇到这样的问题,我们就要想办法解决了。
Spring Bean初始化和销毁Bean的方式虽然后三种,但是第三种是不符合这个,因为Utils是不用继承或者声明接口的,
1、注解方式:
@Component public class TestUtils { @Autowired private ItemService itemService; @Autowired private ItemMapper itemMapper; public static TestUtils testUtils; @PostConstruct public void init() { testUtils = this; } //utils工具类中使用service和mapper接口的方法例子,用"testUtils.xxx.方法" 就可以了 public static void test(Item record){ testUtils.itemMapper.insert(record); testUtils.itemService.queryAll(); } }
我们在init方法中使用以下注解就可以了,时间上这个init()的方法是可以自己随便定义的,注意:inti()方法里面只需要一行代码,跟我这样的就绝对ok了,不用看网上其他人瞎掰!
2、xml配置方式:
我们可以把init()方法上的@PostConstruct注解去掉,在spring-comtext.xml中配置以下bean就好了,里面什么内容都不用写,是不是很简单?
<bean id="testUtils" class="这里写utils类的包全路径名" init-method="init"></bean>
附录: 另外一种Spring bean的初始化和销毁方式
实现InitializingBean, DisposableBean这两个接口,并复写afterPropertiesSet()和destroy()方法
示例代码如下:
- public class InitializingDisposableInit implements InitializingBean,
- DisposableBean {
- @Override
- public void destroy() throws Exception {
- System.out.println("执行InitializingDisposableInit: destroy");
- }
- @Override
- public void afterPropertiesSet() throws Exception {
- System.out.println("执行InitializingDisposableInit: afterPropertiesSet");
- }
- public static void main(String[] args) {
- ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
- "classpath:beans-impl.xml");
- context.close();
- }
- }