strust2环境下使用自定义工厂类生成对象出现怪异现象(工厂类只能在Action类里使用吗?)
背景:
利用自定义工厂类BeanFactory
读取配置文件bean.xml
, 静态代码块生成CustomerService
和CustomerDao
的代理对象. 使用时用方法getBean(String className)
来获取.
错误描述:
其中CustomerService
能够正常获取, 但是CustomerDao
死活是null
.
通过Debug发现, 程序走的流程很是诡异.
Action类里面能够正常使用
BeanFactory.getBean("CustomerService")
, 成功获取CustomerService
对象.
但是
Service
层却获取不到.
debug发现路程走的很是诡异
猜想
经过调试, 发现
在
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论