[seasar-dotnet:1684] Re: 2Container.NET、S2Dao.NET(Windows7)調査について

kubo [E-MAIL ADDRESS DELETED]
2010年 5月 13日 (木) 11:11:51 JST


久保(jflute)です。

発生した現象は、
Win7の環境だと、LogicクラスのDaoの
インジェクションが実行されない、ということですね。
(初期化の中で例外発生したとかではなく)

そして、うまくいくときといかないときの切り分けとして、
「Logicの中のDaoのプロパティに virtual を付けたか否か」

付ける --> インジェクションされる
付けない --> インジェクションされない

しかもこれは、AOP対象のメソッドに virtual を
付けようが付けまいが関係なく上記の結果になる。
(で、合ってます?間違ってたら言って下さいね)
さらに検証を続けるならば、インジェクションされない時に、
Containerから直接 GetComponent() したときに、
果たして、Daoインスタンスが取得できて実行できるのかどうか!?
というところですね。DaoインスタンスのContainer内での生成は
うまくいってて、インジェクションにだけ失敗しているのかどうか。

で、とにもかくにもこの問題とは関係なく、
AOP対象のメソッドに virtual を付けてないと、
トランザクションもトレースも実行されないはずなので、
それはそれでちゃんと付けましょう。
(WinXPやVistaでもトランザクションなしで動いてるはず)

そして、Daoのプロパティに virtual を付けないと
インジェクションされないというのは、確かに変ですね。
(WinXPやVistaでは virtual なんかなくても動くわけなので)

ちなみに、Quillに関しては、
「set { _kojinDao = value; }」が実行されないのは正常な挙動です。
インジェクションの仕方が違うためです。プロパティは経由せずに、
リフレクションでフィールドに直接インジェクションします。
なので、初期化して「set { _kojinDao = value; }」が実行されてなくても、
いざ動かすと _kojinDao にはDaoのインスタンスが存在するはずです。

ちなみに、自分のところにも Quill + DBFlute.NET(+ S2Dao.NET) の
構成で、Win7で正常に動作(実運用)してると報告ありました。
(情報提供ありがとうございます)

そう考えると、Win7上のDynamicProxyで確かにちょっと変なことが
あるのかもしれないけど、Quill と S2Container.NETではDIの方式が
ちょっと違うため、Quill はその影響を受けてない、と仮定できるかも
しれませんね。

で、とりあえず Sfuku さんの得た回避策としては、
Daoのプロパティに virtual を付ければ正常に動作する、
ということになりますかね。
(無論、なぜ動くのかを明確にしないと不安というのもあるので、
時間に余裕があれば、さらに検証を続けた方が良いですが)
Seasar.NETとしては、Quillでは(恐らく)発生していない現象なので、
また、Win7という限定された環境でしか発生しないということもあり、
具体的なアクションはちょっと取れないという感じですね。
(どなたか検証と修正案の検討をして頂ければありがたいですが)

#
# 最後にアドバイスですが、
# 発生した現象や試したことの結果などなど、
# 抽象的な日本語にしない方が良いです。
# 抽象的な日本語を使うにしても、加えて具体的な挙動の説明を
# 必ず添えるようにしましょう。例えば、Daoの作成の失敗、
# という言葉だけだと、受け取り方が読んだ人によって
# マチマチになる可能性がありますから。
# (確かに、全ての言葉を全部説明してたら大変ですが、
# 少なくとも「伝わらなそうだな、誤解されそうだな」
# と思ったら詳細説明(補足)を入れるようにしましょう)
#

2010/5/13 Sohei Fukumura <[E-MAIL ADDRESS DELETED]>:
> お世話になっております。
> Sfukuです。
> 久保(jflute)・hajimeni様ご返信いただきありがとうございます。
>
> 久保(jflute)の何点かもう少し具体的な情報について
>>この時、具体的にアプリケーションでは何が起きますか?
>>A. Init()の最中に例外が発生してしまい、アプリが何も動かない(どんな例外?)
>>B. Init()は正常終了で、アプリ実行時に...が起きる(その何かを具体的に)
> 発生している現象は、Bです。
> アプリケーション実行時に、
> public class KojinLogicImpl : IKojinLogic  {
>        private IKojinDao _kojinDao;
>        public IKojinDao KojinDao
>        {
>            get { return _kojinDao; }
>            set { _kojinDao = value; }
>        }
> KojinLogicImpllクラスで保持しているkojinDaoを参照しにいきますが、
> WindowsXP,VistaではInit()中にset { _kojinDao = value; }を行いますが、
> Windows7ではset { _kojinDao = value; }を行いません。
> そのため、nullオブジェクトにアクセスすることになり、例外が発生します。
>
>>Win7とそれ以外で違った挙動するポイントがあった。
>>具体的には、DynamicAopProxy.csの
>>CreateInterfaceProxy (new Type[] { _type }, target.GetType())
>>の戻り値に違いがあったと。(Win7だと null ?)
>>でしたよね!?
> はい、CreateInterfaceProxy(Logicはclass)ですので
> CreateClassProxyとなりますが、概ねはそのようになります。
>
>>> S2Containerでインスタンスを管理するInterceptorを使用するので、
>>> SingletonS2ContainerFactory.Init()
>>> を行った時にWindows7ではDynamicProxyを作成できていない状況では考慮し難
> い。
>
>>これに関しては、そもそも Quill で同じ現象が発生するかどうか不明。
>>というところですよね?
>>DynamicProxy単体で現象が発生する環境、もしくは、
>>Quillで(同じ構造で)現象が発生する環境で試されてないと思うので。
>> (できれば、これらはあった方が良いです)
> 実は、一旦同じ構造(virtualをつけない)でQuillを使用して行ってみたのですが、
> Containerの初期化まで動作を確認致しましたが、set { _kojinDao = value; }を
> 行えていないことを確認いたしました。
>
>
>>はっきりしているのは、traceInterceptor や requiredTx
>>のAOPのクラス自体のvirtualなのかどうかは無関係です。
>>AOPを掛ける対象のクラス (KojinLogicImpl) における、
>>AOPを掛ける対象のメソッドが virtual という話です。
> ありがとうございます。よくわかりました。
>
>>(もし、他のメソッドに virtual が付いてない場合、
>>そのメソッドに virtual を付けて、プロパティには
>>virtual を付けない場合にどうなりますか?)
> 上記を試した結果、set { _kojinDao = value; }は行われませんでした。
> 逆に、virtual が付いてなくてもプロパティにvirtualがついていれば
> set { _kojinDao = value; }は行われておりました。
>
> hajimeni様のご意見
>>また、他にもAspectをかける箇所は、必ず「virtual」メソッドにしています。
> と、上記に久保(jflute)様からいただきましたご意見を総合すると、
>>AOPを掛ける対象のクラス (KojinLogicImpl) における、
>>AOPを掛ける対象のメソッドが virtual という話
> AOPを掛ける対象のメソッドにvirtualを欠けていなかったというミスのため
> 発生していたような気がいたします。
> 貴重なご意見をいただきましてありがとうございました。
>
> 以上、よろしくお願い致します。
>
>
> hajimeniです。
>
> 横から失礼します。
>
> Quillですが、以下のOSで全て動作しています。
>
> Windows7
> WindowsVista
> Windows Server 2008
>
> S2Dao.netではないですが、同じくInterface型だけで利用するS2Fisshplate.NETを利
> 用していますので、参考になればと思います。
> (Quillはフィールドインジェクションが出来ますのでプロパティではありません
> が・・・)
>
> また、他にもAspectをかける箇所は、必ず「virtual」メソッドにしています。
>
> それはそれとして、Aspectで「Inteface型で受け取るか」って部分は、
> componentを「KojinLogicImpl」で登録して、
> 使うときにインターフェースを指定して
> // プロパティ
> public IKojinLogic KojinLogic
> {get; set;}
> として使うってことじゃないでしょうか?
> (これを使う方もコンポーネント登録が必要でしょうが)
>
> たしか、GetComponent(interface)とすると、interfaceを実装しているクラスも探し
> に行くことが出来たと思うのですけど。
>
> // 現象を見る限り、Pointcutの指定によって、プロパティへのインジェクションが
> 阻害されている感じですね。
>
> 2010年5月12日18:07 kubo <[E-MAIL ADDRESS DELETED]>:
>> 久保(jflute)です。
>>
>> Sfukuさん、ありがとうございます。
>> 状況がわかりやすいものとなりました。
>>
>> ただ、何点かもう少し具体的な情報を頂ければと。
>>
>>> SingletonS2ContainerFactory.Init()
>>> を行った時にWindows7ではDynamicProxyを作成できていないようである。
>>
>> この時、具体的にアプリケーションでは何が起きますか?
>> A. Init()の最中に例外が発生してしまい、アプリが何も動かない(どんな例外?)
>> B. Init()は正常終了で、アプリ実行時に...が起きる(その何かを具体的に)
>>
>>
>> ちなみに、試したことの追加情報として、
>> 以前のメールの内容からすると、RealProxyにすると
>> 問題は発生せずにDBアクセスは正常に動作した。
>> そして、デバッガでDynamicProxyのクラスで
>> Win7とそれ以外で違った挙動するポイントがあった。
>> 具体的には、DynamicAopProxy.csの
>> CreateInterfaceProxy (new Type[] { _type }, target.GetType())
>> の戻り値に違いがあったと。(Win7だと null ?)
>> でしたよね!?
>>
>>> S2Containerでインスタンスを管理するInterceptorを使用するので、
>>> SingletonS2ContainerFactory.Init()
>>> を行った時にWindows7ではDynamicProxyを作成できていない状況では考慮し難
> い。
>>
>> これに関しては、そもそも Quill で同じ現象が発生するかどうか不明。
>> というところですよね?
>> DynamicProxy単体で現象が発生する環境、もしくは、
>> Quillで(同じ構造で)現象が発生する環境で試されてないと思うので。
>> (できれば、これらはあった方が良いです)
>>
>>> 2 Logic のプロパティをvirtualにする
>>> ※Aspectを適用する為には、Inteface型で受け取るか、対象のメソッドがVirtual
>>>> なければならない
>>> public IKojinDao KojinDao
>>> {
>>>        get { return _kojinDao; }
>>>        set { _kojinDao = value; }
>>> }
>>>>>> public virtual IKojinDao KojinDao
>>> {
>>>        get { return _kojinDao; }
>>>        set { _kojinDao = value; }
>>> }
>>> 結果:初期化処理に成功して、Daoにアクセスできデータの検索や登録などができ
>>>> また、DynamicProxyも作成できていた。
>>
>> なるほど、Logic内のDaoのプロパティにvirtualを
>> 付けたらうまく動作したということなのですね。
>> これは恐らく皆が "変な動き" と思うような現象ですね
>> Daoのインスタンスをプロパティにインジェクションするのに、
>> プロパティがオーバーライド可能かどうかは全然関係ないはずなので。
>>
>> LogicクラスのDaoを呼び出しているメソッドに、
>> (もしくは、プロパティ以外のメソッドに)
>> virtual は付いていますか?
>> (もし、他のメソッドに virtual が付いてない場合、
>> その他のメソッドに virtual を付けて、プロパティには
>> viru)
>>
>>> で考えると、"traceInterceptor"や" RequiredTx"がInteface型で受け取るか、対
>>>> のメソッドがVirtualでなければならないということであり、
>>> Info.Logic.Impl.KojinLogicImplのクラスやメソッド自体は、
>>> Inteface型やVirtualでなくても良い。ということになるのでしょうか。
>>
>> ちょっと、表現が曖昧ですね。
>> まず、はっきりしているのは、traceInterceptor や requiredTx
>> のAOPのクラス自体のvirtualなのかどうかは無関係です。
>> AOPを掛ける対象のクラス (KojinLogicImpl) における、
>> AOPを掛ける対象のメソッドが virtual という話です。
>>
>> ただちょっと、"Inteface型で受け取るか" の部分の仕様を
>> 忘れてしまいました...。Quill使ってると、Interfaceを
>> 作らないことが多いので、Interfaceを付けたときに
>> どうなるか、ほとんど試したこと無いので...
>>
>> 動作するケース(2番)があるのであれば、実際にAOPが
>> 掛かっているかどうか、試してみると良いと思います。
>> (virtual付けたときと付けないときと)
>>
>>
>> #
>> # 丸付き数字は極力避けた方がいいですよ
>> #
>> _______________________________________________
>> seasar-dotnet mailing list
>> [E-MAIL ADDRESS DELETED]
>> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>>
>
>
> _______________________________________________
> seasar-dotnet mailing list
> [E-MAIL ADDRESS DELETED]
> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>
> _______________________________________________
> seasar-dotnet mailing list
> [E-MAIL ADDRESS DELETED]
> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>


seasar-dotnet メーリングリストの案内