在普通类里面不能通过@Autowire自动注入service,那么如何调用需要自动注入的service呢?

在Spring管理的web项目里,配置好之后,就可以直接通过@Autowire自动注入获得service;

但是在普通Java类中使用service或者dao就会报空指针异常,因为这个普通类不在Spring的管理下,所以不能使用Spring来注入。

下面讲一下一个普通的Java类如何使用service

先定义SpringContextHolder

package com.fan.framework.context;

import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

/**
 * 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候取出ApplicaitonContext.*/
@Service
@Lazy(false)
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {

    private static ApplicationContext applicationContext = null;

    private static Logger logger = LoggerFactory.getLogger(SpringContextHolder.class);

    /**
     * 取得存储在静态变量中的ApplicationContext.
     */
    public static ApplicationContext getApplicationContext() {
        assertContextInjected();
        return applicationContext;
    }

    /**
     * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        assertContextInjected();
        return (T) applicationContext.getBean(name);
    }

    /**
     * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
     */
    public static <T> T getBean(Class<T> requiredType) {
        assertContextInjected();
        return applicationContext.getBean(requiredType);
    }

    /**
     * 清除SpringContextHolder中的ApplicationContext为Null.
     */
    public static void clearHolder() {
        if (logger.isDebugEnabled()){
            logger.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
        }
        applicationContext = null;
    }

    /**
     * 实现ApplicationContextAware接口, 注入Context到静态变量中.
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
//        logger.debug("注入ApplicationContext到SpringContextHolder:{}", applicationContext);
//        if (SpringContextHolder.applicationContext != null) {
//            logger.info("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);
//        }
        
        SpringContextHolder.applicationContext = applicationContext;
    }

    /**
     * 实现DisposableBean接口, 在Context关闭时清理静态变量.
     */
    @Override
    public void destroy() throws Exception {
        SpringContextHolder.clearHolder();
    }

    /**
     * 检查ApplicationContext不为空.
     */
    private static void assertContextInjected() {
        Validate.validState(applicationContext != null, "applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder.");
    }
    
    
}

然后再使用SpringContextHolder获取指定的service

package com.thinkgem.jeesite.modules.sys.utils;

import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpConfigStorage;
import me.chanjar.weixin.cp.api.WxCpService;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import com.fan.framework.context.SpringContextHolder;
import com.fan.modules.sys.entity.User;
import com.fan.modules.sys.entity.WechatLog;
import com.fan.modules.sys.service.WechatLogService;
import com.thinkgem.jeesite.common.utils.Exceptions;

/**
 * 微信日志*/
public class WechatLogUtils {
    
    private static WechatLogService wechatLogService = SpringContextHolder.getBean(WechatLogService.class);
    
    /**
     * 保存日志
     * @param request
     * @param wxCpService
     * @param wxCpConfigStorage
     * @param qyWechat            微信号名称
     * @param title                操作菜单名称
     * @param user                用户,可为空
     * @param handler
     * @param e                    异常信息
     */
    public static void saveWeChatLog(HttpServletRequest request, WxCpService wxCpService, WxCpConfigStorage wxCpConfigStorage, String qyWechat, String application, String title, String message, User user, Object handler, Exception e) {
        
        WechatLog weChatLog = new WechatLog();
        
        if(StringUtils.isNotBlank(qyWechat)){        // 企业微信
            weChatLog.setQyWechat(qyWechat);
        }
        
        if(StringUtils.isNotBlank(application)){        // 应用
            weChatLog.setApplication(application);
        }
        
        if(null != request && null != wxCpService && null != wxCpConfigStorage){
            weChatLog.setApplication(getAgentName(wxCpService, wxCpConfigStorage));    // 应用
            Map<String, String> map = getMatchedMenu(request, wxCpService, wxCpConfigStorage);
            weChatLog.setFirstLevelMenu(map.get("first_level_menu"));                // 一级菜单
            weChatLog.setSecondLevelMenu(map.get("second_level_menu"));                // 二级菜单
        }
        
        if(null != user){
            weChatLog.setEmployeeNo(user.getLoginName());        // 工号
            weChatLog.setEmployeeName(user.getName());            // 姓名
        }
        
        if(StringUtils.isNotBlank(title)){            // 标题
            weChatLog.setTitle(title);
        }else{
            if(StringUtils.isNotBlank(weChatLog.getApplication())){
                title = weChatLog.getApplication();
                if(StringUtils.isNotBlank(weChatLog.getFirstLevelMenu())){
                    title += ("-"+weChatLog.getFirstLevelMenu());
                }
                if(StringUtils.isNotBlank(weChatLog.getSecondLevelMenu())){
                    title += ("-"+weChatLog.getSecondLevelMenu());
                }
                weChatLog.setTitle(title);
            }
            
        }
        
        Calendar calendar= Calendar.getInstance();
        weChatLog.setCreateDate(calendar.getTime());        // 创建时间
        
        weChatLog.setException(Exceptions.getStackTraceAsString(e));        // 异常消息
        
        if(StringUtils.isNotBlank(message)){
            weChatLog.setMessage(message);
        }
        
        weChatLog.setType(e == null ? WechatLog.TYPE_ACCESS : WechatLog.TYPE_EXCEPTION);    // 日志接入类型(1:接入日志;2:错误日志)
        
        if(null != request){
            weChatLog.setParams(request.getParameterMap());    // 操作提交的数据
            
            weChatLog.setMethod(request.getMethod());        // 提交方式
            
            weChatLog.setUserAgent("");    // 操作用户代理信息
            
            weChatLog.setIp(getRemoteAddr(request));        // ip
            
            weChatLog.setUri(request.getRequestURI());        // uri
        }
        
        // 如果无标题并无异常日志,则不保存信息
        if (StringUtils.isNotBlank(weChatLog.getTitle()) || StringUtils.isNotBlank(weChatLog.getException())){
            // 保存日志信息
            wechatLogService.insert(weChatLog);
        }
        
    }
    /**
     * 获得用户远程地址
     */
    public static String getRemoteAddr(HttpServletRequest request){
        String remoteAddr = request.getHeader("X-Real-IP");
        if (StringUtils.isNotBlank(remoteAddr)) {
            remoteAddr = request.getHeader("X-Forwarded-For");
        }else if (StringUtils.isNotBlank(remoteAddr)) {
            remoteAddr = request.getHeader("Proxy-Client-IP");
        }else if (StringUtils.isNotBlank(remoteAddr)) {
            remoteAddr = request.getHeader("WL-Proxy-Client-IP");
        }
        return remoteAddr != null ? remoteAddr : request.getRemoteAddr();
    }
    
    /**
     * 获取应用
     * https://qyapi.weixin.qq.com/cgi-bin/agent/get?access_token=ACCESS_TOKEN&agentid=AGENTID
     * 返回的是json字符串
     */
    public static String getAgent(WxCpService wxCpService, WxCpConfigStorage wxCpConfigStorage) {
        String accessToken = wxCpConfigStorage.getAccessToken();
        Integer agentId = wxCpConfigStorage.getAgentId();
        String url = "https://qyapi.weixin.qq.com/cgi-bin/agent/get?";
        String info = null;
        try {
            info = wxCpService.get(url, "access_token="+accessToken + "&agentid=" + agentId);
        } catch (WxErrorException e) {
            e.printStackTrace();
        }
        return info;
    }
    
    /**
     * 获取菜单
     * https://qyapi.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN&agentid=AGENTID
     * 返回的是json字符串
     */
    public static String getMenu(WxCpService wxCpService, WxCpConfigStorage wxCpConfigStorage) {
        String accessToken = wxCpConfigStorage.getAccessToken();
        Integer agentId = wxCpConfigStorage.getAgentId();
        String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/get?";
        String menu = null;
        try {
            menu = wxCpService.get(url, "access_token="+accessToken + "&agentid=" + agentId);
        } catch (WxErrorException e) {
            e.printStackTrace();
        }
        return menu;
    }
    
    /**
     * 获取应用中的name
     * @throws WxErrorException
     */
    public static String getAgentName(WxCpService wxCpService, WxCpConfigStorage wxCpConfigStorage) {
        String json = getAgent(wxCpService, wxCpConfigStorage);
        // 响应结果
        JSONObject jsonObject = JSONObject.fromObject(json);
        // name
        String name = (String) jsonObject.get("name");
        return name;
    }
    
    /**
     * 根据uri与获取的菜单相匹配,返回一级菜单和二级菜单
     */
    public static Map<String, String> getMatchedMenu(HttpServletRequest request, WxCpService wxCpService, WxCpConfigStorage wxCpConfigStorage) {
         Map<String, String> matchedMenu = new HashMap<String, String>();
         matchedMenu.put("first_level_menu", "");
         matchedMenu.put("second_level_menu", "");
        String uri = request.getRequestURI();
        if(uri.startsWith("/")){
            uri = uri.replaceFirst("/", "");
        }
        String json = getMenu(wxCpService, wxCpConfigStorage);
        // 响应结果
        JSONObject jsonObject = JSONObject.fromObject(json);
        JSONArray button = jsonObject.getJSONArray("button");
        if(button.size() > 0){
            boolean isBreak = false;
            for (int i = 0; i < button.size(); i++) {
                JSONObject firstObject = JSONObject.fromObject(button.get(i));
                JSONArray subButton = firstObject.getJSONArray("sub_button");
                if(subButton.size() > 0){
                    for(int j = 0 ; j < subButton.size() ; j++){
                        JSONObject secondObject = JSONObject.fromObject(subButton.get(j));
                        String url = (String) secondObject.get("url");
                        if(StringUtils.isNotBlank(url) && url.endsWith(uri)){
                            // 二级菜单的名称
                            String name2 = (String) secondObject.get("name");
                            matchedMenu.put("second_level_menu", name2);
                            // 一级菜单的名称
                            String name1 = (String) firstObject.get("name");
                            matchedMenu.put("first_level_menu", name1);
                            isBreak = true;
                            break;
                        }
                    }
                    if(isBreak){
                        break;
                    }
                }
            }
        }
        return matchedMenu;
    }
    
}

另外一种方法是

先编写一个类来实现ApplicationContextAware

/**
 * 通过该类即可在普通工具类里获取spring管理的bean
 */
public final class SpringTool implements ApplicationContextAware {
    private static ApplicationContext applicationContext = null;
 
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringTool.applicationContext == null) {
            SpringTool.applicationContext = applicationContext;
            System.out.println(
                    "========ApplicationContext配置成功,在普通类可以通过调用ToolSpring.getAppContext()获取applicationContext对象,applicationContext="
                            + applicationContext + "========");
        }
    }
 
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
 
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }
}

然后把这个类加到spring的配置文件中去

<bean class="com.xsl.spring.SpringTool"/>

这样就可以在任何一个普通的工具类里,根据spring里配置好的bean的id,得到这个注入好的对象了

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath*:spring/spring-context.xml")
public class JmFposStoreSalesTest {
    @Test
    public void test() {
        WechatLogService wechatLogService = (WechatLogService) SpringTool.getBean("articleService");
        // 再进行其它操作
        
    }
}
原文地址:https://www.cnblogs.com/xsl1995/p/9177688.html