(xml configの代わりに)AOPのアノテーションの使用について友人に示すための簡単なクラスのセットを作成しました。@ComponentScanを機能させることができず、AnnotationConfigApplicationContextgetBeanも誤動作します。私は2つのことを理解したかった。以下のコードを参照してください:
PersonOperationsI.java
package samples.chapter3;
import org.springframework.stereotype.Component;
@Component
public interface PersonOperationsI {
public String getName();
}
PersonOperations.java
/**
*
*/
package samples.chapter3;
import org.springframework.stereotype.Component;
@Component
public class PersonOperations implements PersonOperationsI {
public String getName() {
return "";
}
}
PersonOperationsConfigClass.java
package samples.chapter3;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
//question2 - Below Component Scan didnt work - Test Case failing in setup()
//@ComponentScan(basePackages = {"samples.chapter3"})
@EnableAspectJAutoProxy
public class PersonOperationsConfigClass {
}
PersonOperationsAdvice.java
/**
*
*/
package samples.chapter3;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class PersonOperationsAdvice {
/**
* execution( [Modifiers] [ReturnType] [FullClassName].[MethodName]
([Arguments]) throws [ExceptionType])
* @param joinPoint
* @return
*/
@Before("execution(public * samples.chapter3.PersonOperations.getName()))")
public String beforeGetName(JoinPoint joinPoint) {
System.out.println("method name = " + joinPoint.getSignature().getName());
return null;
}
}
PersonOperationsTest.java
package samples.chapter3;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = { PersonOperationsConfigClass.class })
public class PersonOperationsTest {
//@Autowired
private PersonOperationsI obj;
@Before
public void setUp() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("samples.chapter3");
ctx.refresh();
obj = ctx.getBean(PersonOperationsI.class);
//obj = ctx.getBean(PersonOperations.class);//getBean of Child class not working - why ?
Assert.assertNotNull(obj);
ctx.close();
}
@Test
public void test() {
System.out.println(obj.getName());
}
}
質問1- @ componentscanが機能しない理由。テストケースでAnnotationConfigApplicationContextを使用せず、@ componentscanとautowiredに依存している場合、テストケースのオブジェクトはnullです。
質問2-子クラスのctx.getBean(PersonOperations.class); // getBeanが機能しない-なぜですか?
通常@ComponentScan
、@Configuration
アノテーション付きクラスと一緒に使用する必要があります。引数なしの@ComponentScanは、現在のパッケージとそのすべてのサブパッケージをスキャンするようにSpringに指示することに注意してください。。
@Componentクラスはとても不要になった使用のXML設定にそのタイプのBeanを作成するために春を告げる、そして豆は=>なしインターフェース/抽象クラスをインスタンス化することができるクラスです。したがって、あなたの場合は、@ Componentをから削除し、。PersonOperationsI
にのみ残す必要がありPersonOperations
ます。クラスに@Componentアノテーションを付ける場合、Beanに付けられるデフォルトの名前は、最初の文字が下のクラス名であるため、ctx.getBean("personOperationsI")
またはを呼び出す必要があります。ctx.getBean(PersonOperations.class)
そして将来のために、インターフェースと実装のためのこれらの命名規則を読んでください。あなたの場合、私は以下を変更します:PersonOperationsI
toOperations
質問2
あなたが言ったように、Beanスキャンプロセスは完了していなかったので、コンテキストにBeanはなく、どちらの方法でもコンテキストからBeanを期待するべきではありません(どちらの方法もnullを返します)。@Autowired
context.getBean
以下のリンクには、Beanスキャンの詳細があります(役立つ場合があります)
Springコンポーネントのスキャン
A1、「ApplicationContextのロードに使用するコンポーネントクラス」@ComponentScan
からコメントアウトされているため、機能しませんでした。またはPersonOperationsConfigClass
@Configuration
//@ComponentScan(basePackages = {"samples.chapter3"})
@EnableAspectJAutoProxy
public class PersonOperationsConfigClass {}
テストクラスは、@ ContextConfigurationアノテーションで指定されたコンポーネントクラスから作成されたApplicationContextを取得します。コンポーネントが作成されていないか、自動検出されていないため、@Autowired
失敗しました。
AnnotationConfigApplicationContext
アノテーションが付けられたメソッド内でが使用された場合@Before
、ApplicationContextがプログラムで作成されました。ctx.scan("samples.chapter3");
スキャンされ、。でPersonOperations
注釈が付けられた自動検出@Component
。obj
参照はコードで設定されましたobj = ctx.getBean(PersonOperationsI.class);
。このオブジェクトは「自動配線」ではありませんでした。
OPからのコメントに基づいて更新
Junit 4アノテーションと@ExtendWith(SpringExtension.class)の組み合わせが機能していません。
次のテストクラスは、エラー/失敗なしで正常に実行されます。obj
自動配線され、nullではありません。Junit5の対応するアノテーションを使用しました。
package rg.app.aop.so.q1;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes= {PersonOperationsConfigClass.class})
public class PersonOperationsTest {
@Autowired
private PersonOperationsI obj;
@BeforeEach
public void setUp() {
System.out.println("init ::"+ obj);
Assertions.assertNotNull(obj);
}
@Test
public void testPersonOps() {
Assertions.assertNotNull(obj);
}
}
構成クラス
package rg.app.aop.so.q1;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = {"rg.app.aop.so.q1"})
public class PersonOperationsConfigClass {
}
A2、以下は私の分析です。
覚えておいてください、属性の@EnableAspectJAutoProxy
デフォルト値は「false」proxyTargetClass
です。この属性は、プロキシメカニズムを決定します:JDKプロキシ(false)またはCGLIBプロキシ(true)。
ここで、有効なアドバイスを持つ有効なアスペクトが存在すると、実際にプロキシが開始されます。コンポーネントは、アドバイスがそれに影響を与える場合にのみプロキシされます。つまり、コンポーネントのプロキシは、必要な場合にのみ発生します。
ケース1
いつ:@EnableAspectJAutoProxy
/@EnableAspectJAutoProxy(proxyTargetClass = false )
ctx.getBean(InterfaceType)
Beanを返しますctx.getBean(ImplementationClassType)
Beanを返さないケース2
いつ : @EnableAspectJAutoProxy(proxyTargetClass = true )
ctx.getBean(InterfaceType)
Beanを返しますctx.getBean(ImplementationClassType)
Beanを返しますケース3
いつ:@EnableAspectJAutoProxy
注釈がない
ctx.getBean(InterfaceType)
Beanを返しますctx.getBean(ImplementationClassType)
Beanを返しますケース1、SpringAOPはproxyTargetClass
falseとして有効になっています。JDKプロキシは、インターフェースタイプのプロキシBeanを作成します。作成されるBeanのタイプはInterfaceTypeであり、ImplementationClassTypeではありません。これは、ctx.getBean(ImplementationClassType)がBeanを返さない理由を説明しています。
ケース2、SpringAOPはproxyTargetClass
trueとして有効になっています。CGLIBは、アノテーションが付けられたクラスをサブクラス化することによってプロキシBeanを作成し@Component
ます。作成されたBeanはImplementationClassType型であり、InterfaceTypeとしての資格もあります。したがって、両方のgetBean()呼び出しは、このBeanを正常に返します。
ケース3、
Springは、特別な処理が必要な場合にのみ「プロキシ」オブジェクトを作成します(例:AOP、トランザクション管理)。
このロジックでは、@EnableAspectJAutoProxy
が存在し@Component
ないため、プロキシなしでアノテーションが付けられたクラスに対してBeanが作成されます。作成されたBeanはImplementationClassType型であり、InterfaceTypeとしての資格もあります。したがって、両方のgetBean()呼び出しは、このBeanを正常に返します。
次のコードで分析を行います。
package rg.app.aop.so.q1;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class AppMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("rg.app.aop.so.q1");
ctx.refresh();
System.out.println();
for(String name:ctx.getBeanNamesForType(PersonOperationsI.class)) {
System.out.println(name);
}
for(String name:ctx.getBeanNamesForType(PersonOperations.class)) {
System.out.println(name);
}
PersonOperationsI obj = ctx.getBean(PersonOperationsI.class);
System.out.println(obj.getClass());
obj = ctx.getBean(PersonOperations.class);
System.out.println(obj.getClass());
ctx.registerShutdownHook();
}
}
ケース1のプリント
personOperations
class com.sun.proxy.$Proxy18
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'rg.app.aop.so.q1.PersonOperations' available
ケース2プリント
personOperations
personOperations
class rg.app.aop.so.q1.PersonOperations$$EnhancerBySpringCGLIB$$c179e7f2 class rg.app.aop.so.q1.PersonOperations$$EnhancerBySpringCGLIB$$c179e7f2
ケース3プリント
personOperations
personOperations
class rg.app.aop.so.q1.PersonOperations
class rg.app.aop.so.q1.PersonOperations
お役に立てれば
Reba McEntire が息子の Shelby Blackstock と共有しているクリスマスの伝統について学びましょう。
メーガン・マークルとマライア・キャリーが自然な髪の上でどのように結合したかについて、メーガンの「アーキタイプ」ポッドキャストのエピソードで学びましょう.
ハリー王子が家族、特にチャールズ王とウィリアム王子との関係について望んでいると主張したある情報源を発見してください。
ワイノナ・ジャッドが、母親のナオミ・ジャッドが亡くなってから初めての感謝祭のお祝いを主催しているときに、彼女が今では家長であることをどのように認識したかを学びましょう.
Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?
The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!
ロザンヌ・バーが自分自身でいるだけでABCショーの再起動を破壊するのに、60日強かかりました。ロザンヌは、ツイッターで帽子をかぶったトロールであり、白人至上主義者に傾倒し、陰謀論者を愛する「Make AmericaGreatAmerica」であり続けています。
仕事の打ち合わせをしていると、招待される人が多ければ多いほど、全体が狂いやすくなります。そのため、すべての打ち合わせには、話題を維持するための打ち合わせ「警察」が必要です。全員が集まって話し合う間今週終了する大きなプロジェクトについては、必然的に誰かが「私たちはみんなここにいるので…」と決めるでしょう。数週間後に起こっている別のプロジェクトを立ち上げるのは良い考えです。コーヒーメーカーはどうしたの?壊れていますか?そして、ジョンの新しい子犬を見たことがありますか?会話を中断して、10分間写真を見てみましょう。
5月のリリースの特に強力なラインナップに続いて、6月はNeko Case、Nas、Lykke Li、Gang Gang Danceから待望のリターンをもたらし、Drake、Oneohtrix Point Never、Zeal&Ardourからの期待された努力とSnailMailからの有望なデビューをもたらしますとジュリアーナドーティ。ヒップホップでは、間違いなくカニエの月であり、ラッパープロデューサーは毎週少なくとも1回のリリースに関与しています。
ロシアのフィギュアスケーター、カミラ・バリエバが関与したドーピング事件が整理されているため、チームは2022年北京冬季オリンピックで獲得したメダルを待っています。
何千人ものAmazonの買い物客がMulberry Silk Pillowcaseを推奨しており、現在販売中. シルクの枕カバーにはいくつかの色があり、髪を柔らかく肌を透明に保ちます。Amazonで最大46%オフになっている間にシルクの枕カバーを購入してください
ラファイエット警察署は、「不審な男性が女性に近づいた」という複数の苦情を受けて、12 月にパデュー大学の教授の捜査を開始しました。
私たちの周りの世界と同じように、言語は常に変化しています。以前の時代では、言語の変化は数年または数十年にわたって発生していましたが、現在では数日または数時間で変化する可能性があります。
認知症を患っている 91 歳のアジア人女性が最近、47 番街のアウター サンセット地区でロメオ ロレンゾ パーハムに襲われました。伝えられるところによると、被害者はサンフランシスコの通りを歩いていたところ、容疑者に近づき、攻撃を受け、暴行を受けました。
“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.
人々にチャンスを与えることは、人生で少し遅すぎると私は信じています。寛大に。