strust2环境下使用自定义工厂类生成对象出现怪异现象(工厂类只能在Action类里使用吗?)

发布于 2022-09-06 05:14:19 字数 4831 浏览 22 评论 0

背景:

利用自定义工厂类BeanFactory读取配置文件bean.xml, 静态代码块生成CustomerServiceCustomerDao的代理对象. 使用时用方法getBean(String className)来获取.

错误描述:

其中CustomerService能够正常获取, 但是CustomerDao死活是null.
通过Debug发现, 程序走的流程很是诡异.

  • Action类里面能够正常使用BeanFactory.getBean("CustomerService"), 成功获取CustomerService对象.

clipboard.png

  • 但是Service层却获取不到.

clipboard.png

  • debug发现路程走的很是诡异

clipboard.png

猜想

经过调试, 发现

  • Action类里面使用工厂类, 都能够成功获取.

  • 另外, 这个工厂类以前没有struts2时是可以正常使用的.

  • 并且, 不启动tomcat, 仅仅junit.Test也能够成功获取对象.

综上所述, 我猜测struts2+tomcat+工厂模式+代理, 导致程序诡异的bug

请高人指点这其中原因!

测试成功时的源码

即均在action类中使用工厂类.

Action类

public class CustomerAction extends ActionSupport {
    // 获取dao对象
    private CustomerDao customerDao = new CustomerDaoImpl();

    // 获取service对象
    private CustomerService customerService = (CustomerService) BeanFactory.getBean("CustomerService");

    public String list() {
        Debug.log("进入list方法");
        // 在action类中生成CustomerDao, 并调用方法测试
        customerDao.dao();

        // 查询所有客户
        List<Customer> list = customerService.findAll();

        // 返回值
        HttpServletRequest request = ServletActionContext.getRequest();
//        request.setAttribute("list", list);
        Debug.log("退出list方法");
        return SUCCESS;
    }

}

工厂类

package com.ssh.nisus.factory;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * dao层实现类生成工厂
 * Author: Nisus-Liu
 * Date: 2017-11-16-22:58
 */
public class BeanFactory {
    // map用来粗放创建的bean们
    private static Map<String, Object> beans = new HashMap<String, Object>();
    // 工厂只需要在项目启动创建一次即可 --> 静态代码块
    static{
        SAXReader rder = new SAXReader();
        try {
            ClassLoader loader = BeanFactory.class.getClassLoader();
            Document xml = rder.read(loader.getResourceAsStream("beans.xml"));
            Element root = xml.getRootElement();
            List<Element> el2s = root.elements();
            for (Element el : el2s) {
                String id = el.attributeValue("id");
                String className = el.attributeValue("class");
                // 获取当前类
                Class clz = Class.forName(className);
                // 获取当前对象
                final Object o = clz.newInstance();
//                beans.put(id, o);     // 这是初级的获取对象自己

                // 进阶: 获取对象的代理对象
                Object proxyInstance = Proxy.newProxyInstance(
                        loader,
                        clz.getInterfaces(),        // 返回代理对象刚好实现了id指定的接口, 这样用的时候就可以id指定的类接收
                        new InvocationHandler() {
                            @Override
                            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                // 代理对象调用方法时, 这个method就产生了
                                System.out.println("开始调用方法:" + o.getClass().getName() + "." + method.getName());

                                // 调用被对象自己的方法
                                Object result = method.invoke(o, args);

                                System.out.println("调用方法结束: " + o.getClass().getName() + "." + method.getName());
                                return result;
                            }
                        }
                );

                beans.put(id, proxyInstance);
            }


        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }

    public static Object getBean(String className) {
        return beans.get(className);
    }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文