ejb3.0学习之二:有状态会话bean开发

1、说明:

有状态的会话bean与无状态的会话bean是有区别的

a.无状态会话bean中ejb组件会使他忘记过去,他不会维护方法调用其间的会话信息。

b.而有状态的就不一样,ejb容器会维护其方法调用的会话信息。他和无状态的生命周期都是有ejb容器控制的(当然容器有自己的一套算法,知道哪些bean该销毁哪些不该销毁),当需要一个有状态的会话bean的时候EJB容器会构造出该bean,当一断时间没有用到这个bean的时候ejb容器会执行“挂起”策略将该bean由内存写入到硬盘中,当需要的时候就会激活它

2、下面就开始有状态的会话bean学习吧

首先我们在上次的项目基础上建一个statefull包

a.Statefull接口的源代码加说明

package statefull;
/**
 * 有状态会话bean
 * @author zhenlai
 *
 */
public interface Statefull {
	/**
	 * 计数器递增1
	 * @return
	 */
	public int count();
	
	/**
	 * 对计数器进行值位
	 * @param value
	 */
	public void set(int value);
	
	/**
	 * 删除计数器
	 */
	public void remove();
}
b.StatefullBean接口的源代码加说明

package statefull;

import javax.ejb.Remote;
import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.interceptor.Interceptors;

/**
 * 有状态会话bean
 * bean实例会维护一个整数,存在业务方法来实现递增
 * @author zhenlai
 *
 */
@Stateful
@Remote(Statefull.class)
@Interceptors(StatefullCallBack.class)
public class StatefullBean implements Statefull {
	/*
	 * 无参构造器
	 */
	public StatefullBean() {
		System.out.println("StatefullBean实例化了");
	}

	/*
	 * 维护会话bean的计数器
	 */
	private int value;
	
	/**
	 * count业务方法
	 */
	public int count() {
		System.out.println("count业务方法被调用了");
		return ++value;
	}

	/**
	 * set业务方法
	 */
	public void set(int value) {
		this.value = value;
		System.out.println("set业务方法被调用了");
	}

	/**
	 * 使用remove注解,执行这个方法后ejb容器会销毁当前的bean
	 */
	@Remove
	public void remove() {
		System.out.println("remove方法被调用了");
	}

}

c.StatefullCallBack接口的源代码加说明

package statefull;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.PostActivate;
import javax.ejb.PrePassivate;
import javax.interceptor.InvocationContext;

/**
 * 生命周期回调拦截器,共
 * @author zhenlai
 *
 */
public class StatefullCallBack {

	/**
	 * 无参构造器
	 */
	public StatefullCallBack() {
	}
	
	/**
	 * 构建bean后EJB容器会调用它
	 * @param ctx
	 * @throws Exception
	 */
	@PostConstruct
	public void construct(InvocationContext ctx) throws Exception{
		System.out.println("StatefullCallBack的construct方法被调用啦");
		ctx.proceed();
	}
	
	/**
	 * 激活bean后EJB容器会调用它
	 * @param ctx
	 * @throws Exception
	 */
	@PostActivate
	public void activate(InvocationContext ctx) throws Exception{
		System.out.println("StatefullCallBack的activate方法被调用啦");
		ctx.proceed();
	}
	
	/**
	 * 挂起bean前EJB容器会调用它
	 * @param ctx
	 * @throws Exception
	 */
	@PrePassivate
	public void passivate(InvocationContext ctx) throws Exception{
		System.out.println("StatefullCallBack的passivate方法被调用啦");
		ctx.proceed();
	}
	
	/**
	 * 销毁bean前EJB容器会调用它
	 * @param ctx
	 * @throws Exception
	 */
	@PreDestroy
	public void destory(InvocationContext ctx) throws Exception{
		System.out.println("StatefullCallBack的destory方法被调用啦");
		ctx.proceed();
	}
}

d.客户端代码和说明

package statefull;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;
/**
 * 客户端
 * @author zhenlai
 *
 */
public class Client {
	/* 客户端数目*/
	public static final int CLIENTS = 3;
	
	public static void main(String[] args) throws NamingException, InterruptedException {
		/*参数信息*/
		Properties props = new Properties();
		props.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
		props.setProperty("java.naming.provider.url", "localhost:1099");
		props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming");
		
		/*获得上下文*/
		InitialContext ctx = new InitialContext(props);
		
		/*持有有状态bean数组*/
		Statefull statefull[] = new Statefull[3];
		int value = 0;
		
		/*创建数组的成员,调用各自的count方法*/
		System.out.println("开始实例化 bean");
		for (int i = 0; i < CLIENTS; i++) {
			statefull[i] = (Statefull) ctx.lookup("StatefullBean/remote");
			
			/*初始化计数器*/
			statefull[i].set(value);
			
			/*加1并打印*/
			value = statefull[i].count();
			System.out.println("value="+value);
			
			/*sleep100ms*/
			Thread.sleep(100);
		}
		
		/*
		 * 为了证明挂起和激活是否被EJB容器正确处理
		 * 调用了Bean的实例count方法
		 */
		System.out.println("调用bean的count方法");
		for (int i = 0; i < CLIENTS; i++) {
			/* 加1并打印*/
			value = statefull[i].count();
			System.out.println("value="+value);
			
			/* 调用remove方法,让EJB容器销毁当前bean*/
			statefull[i].remove();
		}
		
		/* sleep50ms*/
		Thread.sleep(50);
	}
}
(说明:为了理解有状态的会话bean的运行过程,在这里加入了StatefullCallBack回调函数)

然后发布该项目,启动jboss,运行客户端看看结果

3.结果

客户端如下:

开始实例化 bean
value=1
value=2
value=3
调用bean的count方法
value=2
value=3
value=4

服务器输出结果如下:

 StatefullBean实例化了
 StatefullCallBack的construct方法被调用啦
 set业务方法被调用了
 count业务方法被调用了
 StatefullBean实例化了
 StatefullCallBack的construct方法被调用啦
 set业务方法被调用了
 count业务方法被调用了
 StatefullBean实例化了
 StatefullCallBack的construct方法被调用啦
 set业务方法被调用了
 count业务方法被调用了
 count业务方法被调用了
 remove方法被调用了
 StatefullCallBack的destory方法被调用啦
 count业务方法被调用了
 remove方法被调用了
 StatefullCallBack的destory方法被调用啦
 count业务方法被调用了
 remove方法被调用了
 StatefullCallBack的destory方法被调用啦
(根据上面结果可以看出来ejb容器确实有激活和挂起操作,这里挂起不是很明显因为ejb觉得该bean还不需要挂起,当然没有挂起也就没有激活,这里大家可以把该bean改成无状态的对比一下运行结果,这样印象会更深刻,ok有状态bean告一段落。下一节将会介绍无状态和有状态bean的生命周期,敬请关注!)


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值