seam中的factory

实现原理

工厂的定义有三种方式 1<factory method  2<factory value 3)组件类中的@Factory(

Component.getInstance

所有组件的使用都是从Component.getInstance开始的,包括Namefactory

1)  首先从上下文中找组件

2)  如果找不到再通过工厂定义创建或组件定义newInstance

3)  将结果进行Unwrap处理,如果结果不是组件实例并且组件有Unwrap注释,就直接返回结果,否则报异常;如果结果是组件实例再进行Unwrap处理

Object result = Contexts.lookupInStatefulContexts(name);

if (result==null && create)

      {

        result = getInstanceFromFactory(name);

        if (result==null)

        {

           if (component==null)

           {

           }

           else if ( component.getScope().isContextActive() )

           {

              result = component.newInstance();

           }

        }

      }

if (result!=null)

      {

         if (component!=null)

         {

            if ( !component.isInstance(result) )不是组件的实例,有Unwrap注释就直接返回,没有报异常

            {

               if ( component.hasUnwrapMethod() ) return result; ///best way???

               throw new IllegalArgumentException( "….”);

            }

            result = component.unwrap(result);获取的是组件,再进行unwrap处理

         }

      }

getInstanceFromFactory(String name)

三种工厂定义都设置进Init中,配置优先与类中定义

Init init = Init.instance();

      if (init==null) //for unit tests, yew!

      {

         return null;

      }

      else

      {

         Init.FactoryMethod factoryMethod = init.getFactory(name);

//组件方法工厂,执行组件的方法

         Init.FactoryExpression methodBinding = init.getFactoryMethodExpression(name);

//配置方法工厂

         Init.FactoryExpression valueBinding = init.getFactoryValueExpression(name);

//配置值工厂

         if ( methodBinding!=null && getOutScope( methodBinding.getScope(), null ).isContextActive() ) //let the XML take precedence

         {

            Object result = methodBinding.getMethodBinding().invoke();

            return handleFactoryMethodResult( name, null, result, methodBinding.getScope() );

         }

         else if ( valueBinding!=null && getOutScope( valueBinding.getScope(), null ).isContextActive() ) //let the XML take precedence

         {

            Object result = valueBinding.getValueBinding().getValue();

            return handleFactoryMethodResult( name, null, result, valueBinding.getScope() );

         }

         else if ( factoryMethod!=null && getOutScope( factoryMethod.getScope(), factoryMethod.getComponent() ).isContextActive() )

         {

            Object factory = Component.getInstance( factoryMethod.getComponent().getName(), true );

            if (factory==null)

            {

               return null;

            }

            else

            {

               Object result = factoryMethod.getComponent().callComponentMethod( factory, factoryMethod.getMethod() );

               return handleFactoryMethodResult( name, factoryMethod.getComponent(), result, factoryMethod.getScope() );

            }

         }

         else

         {

            return null;

         }

      }

handleFactoryMethodResult

result为工厂方法返回的值或值绑定的值,如果

handleFactoryMethodResult(String name, Component component, Object result, ScopeType scope)

   {

      Object value = Contexts.lookupInStatefulContexts(name); //see if a value was outjected by the factory method

      if (value==null) //usually a factory method returning a value

      {

         ScopeType outScope = getOutScope(scope, component);

         if ( outScope!=STATELESS )

         {

            outScope.getContext().set(name, result);

         }

         return result;

      }

      else //usually a factory method with a void return type

      {

         if (scope!=UNSPECIFIED)

         {

            throw new IllegalArgumentException("factory method with defined scope outjected a value: " + name);

         }

         return value;

在配置文件

1<factory> 声明让你指定一个值或者方法来绑定一个表达式,当它第一次被引用时,将被执行用来初始化一个context变量的值。

 

<factory name="contact" method="#{contactManager.loadContact}" scope="CONVERSATION"/>

<factory name="user" value="#{actor}" scope="STATELESS"/>

<factory name="contact" value="#{contactManager.contact}" scope="STATELESS"/>

 

2)你也可以为Seam组件创建一个别名(第二个名字)

<factory name="user" value="#{actor}" scope="STATELESS"/>

<factory name="contact" value="#{contactManager.contact}" scope="STATELESS"/>

 

3auto-create="true" 用在 <factory> 声明中尤其常见

<factory name="session" value="#{entityManager.delegate}" scope="STATELESS" auto-create="true"/>

在组件类中

有两种工厂方法。

第一种返回一个值,Seam会把它绑定到上下文里:

第二种方法返回 void,它自己把值绑定到上下文变量:

@Factory(scope=CONVERSATION)
public List<Customer> getCustomerList() {//没有指定工厂名字就按bean取方法名称
    return ... ;
} 
 
 
与类的属性配合使用
@DataModel List<Customer> customerList;
@Factory("customerList")
public void initCustomerList() {
    customerList = ...  ;
} 

@Unwrap

一个组件只能有一个@Unwrap

 

两种情况下,当我们引用 customerList 上下文变量,而其值为null时,工厂方法被调用,然后对这个值生命周期的其他部分就无法操纵了。更加强大的模式是 manager component pattern(管理者组件模式)。 在这种情况下,有一个Seam组件绑定到上下文变量,它管理着上下文变量的值,对客户端不可见。

管理者组件可以是任何组件,它需要一个 @Unwrap 方法。 该方法返回对客户端可见的值,每次 上下文变量被引用的时候都会被调用。

@Name("customerList")
@Scope(CONVERSATION)
public class CustomerListManager
{
    ...</
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值