配置文件+抽象工厂+反射

8 篇文章 0 订阅

 Java-web编程的逻辑为:客户端-->servlet-->manager-->dao-->数据库,然后在把数据一层一层返回去,显示给用户。

其中在servlet中要调用manager的方法,就要先实例化一下它;在manager层调用dao就要实例化dao。这样,每一层做的事就不是很纯粹了,不符合高内聚的理论,系统不够灵活。我们就要用一个可以生产各种产品的工厂把他们都生产出来,每一层都和工厂去要,这样就屏蔽了生产细节,也符合现实世界的情况。

1、建立一个配置文件beans-config.xml   (其中id为manager接口路径、dao接口路径,class为实现的具体类的路径)

<?xml version="1.0" encoding="UTF-8"?>
<beans>
	<service-class>
		<service id="com.cxc.drp.basedata.manager.ItemManager" class="com.cxc.drp.basedata.manager.ItemManagerImpl" />
	</service-class>
	
	<dao-class>
		<dao id="com.cxc.drp.basedata.dao.ItemDao" class="com.cxc.drp.basedata.dao.ItemDaoForOracle" />
	</dao-class>
	
</beans>

2、建立工厂,因为就两个产品就不抽象了,因为抽象还要多建类。这个产品是固定的,就两个,不会在加产品了,要灵活运用抽象工厂。(模式只是一个交流的术语,工厂就是生产一类产品,比如电视工厂:可以生产海尔、长虹等等,但是只能生产一类产品。抽象工厂可以生产一系列产品,电视、冰箱、车、电脑都行,这样多个产品流的工厂就叫抽象工厂)

/**
 * 抽象工厂,主要创建两个系列产品
 * manager系列
 * dao系列
 * @author 曹学成
 *
 */
public class BeanFactory {
        /*
        运用单例,只能有一个BeanFactory
        单例三要素:
        1、静态实例化instance
        2、构造函数
        3、静态的getInstance方法,并返回instance
        */
        //1、静态实例化instance
	private static BeanFactory instance =new BeanFactory();
        //配置文件的名称
	private final String beansConfigFile="beans-config.xml";
	//保存service相关对象
	private Map serviceMap=new HashMap();
	//保存dao相关对象
	private Map daoMap=new HashMap();
	private Document doc;
        //2、构造函数
	private BeanFactory(){
		try{
                //读配置文件内容
			doc=new SAXReader().read(Thread.currentThread().getContextClassLoader().getResourceAsStream(beansConfigFile));
		}catch (DocumentException e) {
			e.printStackTrace();
			throw new RuntimeException();
		}
	}
        //3、静态的getInstance方法,并返回instance
	public static BeanFactory getInstance(){
		return instance;
	}
	/**
	 * 根据产品取得service系列产品
	 * 如果service已经实例化就不再实例化,直接用;否则就实例化
         *synchronized 同步的关键字,确保线程安全
	 * @param beanId
	 * @return
	 */
	public synchronized Object getServiceObject(Class s){
		if(serviceMap.containsKey(s.getName())){
			return serviceMap.get(s.getName());
		}
		Element beanElement=(Element) doc.selectSingleNode("//service[@id=\""+s.getName() +"\"]");
		String className= beanElement.attributeValue("class");
		Object service=null;
		try {
			service= Class.forName(className).newInstance();
			 //将创建的对象放入map中
			 serviceMap.put(s.getName(), service);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException();
		} 
		return service;
	}
	/**
	 * 根据产品取得dao系列产品
	 * 如果dao已经实例化就不再实例化,直接用;否则就实例化
         *synchronized 同步的关键字,确保线程安全
	 * @param beanId
	 * @return
	 */
	public synchronized Object getDaoObject(Class c){
		if(daoMap.containsKey(c.getName())){
			return daoMap.get(c.getName());
		}
		Element beanElement=(Element) doc.selectSingleNode("//dao[@id=\""+c.getName() +"\"]");
		String className= beanElement.attributeValue("class");
		Object dao=null;
		try {
			dao= Class.forName(className).newInstance();
			 //将创建的对象放入map中
			daoMap.put(c.getName(), dao);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException();
		} 
		return dao;
	}

3、各层用这个工厂就行了

manager层

private ItemDao itemDao=null;
    //在构造函数里面把itemDao付好值,增删改查直接用
public ItemManagerImpl() {
		itemDao=(ItemDao)BeanFactory.getInstance().getDaoObject(ItemDao.class);
                }

Servlet层

因为servlet有很多,每一层写这个代码很麻烦,所以提取一个AbstractItemServlet。又希望在Tomcat启动时,就把工厂实例化好,因为这个比较费时。

    (1)InitServlet

public class InitServlet extends HttpServlet {
	@Override
	public void init() throws ServletException {
	//将抽象工厂放到servletContext中
	System.out.println("创建系统的beanFactory");
	BeanFactory beanFactory=BeanFactory.getInstance();
	this.getServletContext().setAttribute("beanFacotry", beanFactory);
	
	}
}

然后在web.xml中配置一下

讲解:

  • load-on-startup标记容器是否在启动的时候实例化并调用其init()方法的优先级

  • 它的值表示servlet应该被载入的顺序

  • 当值为0或者大于0时,表示容器在应用启动时就加载并初始化这个servlet;

  • 如果值小于0或未指定时,则表示只有在第一次请求的容器才在该servlet调用初始化函数

  • 正值越小,servlet的优先级越高,应用启动时就越先加载。

  • 值相同时,容器就会自己选择顺序来加载。

 <servlet>
  	<servlet-name>InitServlet</servlet-name>
  	<servlet-class>com.cxc.drp.util.InitServlet</servlet-class>
  	<load-on-startup>2</load-on-startup>	   <!--2表示在servlet初始化就加载  -->
    </servlet>

       (2)AbstractItemServlet

public class AbstractItemServlet extends HttpServlet {
	protected ItemManager itemManager;
	@Override
	public void init() throws ServletException {
BeanFactory.getInstance().getServiceObject("itemManager");
//读取放入servletContext中的抽象工厂
		BeanFactory beanFactory=(BeanFactory)this.getServletContext().getAttribute("beanFactory");
		ItemManager itemManager=(ItemManager) beanFactory.getServiceObject(ItemManager.class);
	}

      (3)各个具体的servlet继承抽象的servlet,然后用manager就行了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值