IoCコンテナ(2):@Autowired,構成部品スキャン,空スキャン


5. @Autowired


必要な依存オブジェクトのタイプ(Type)に対応する空を検索して入力します.
@Autowired
要求
  • :デフォルト値はtrue(見つからない場合はアプリケーションが失敗)
  • です.
    使用可能な場所
  • ジェネレータ(スプリング4.3から省略)
  • .
  • Setter
  • フィールド
  • 作成者またはフィールドに依存性を注入しようとすると、オブジェクト自体を作成できますが、@Autowiredというコメントが追加されている場合は、依存性を注入するには空きが必要なため、アプリケーションを駆動できません.この場合、@Autowired(required=false)として指定できます.
    public class BookRepository {
    }
    
    @Service
    public class BookService {
        BookRepository bookRepository;
        
        @Autowired(required = False)
        public void setBookRepository(BookRepository bookRepository) {
            this.bookRepository = bookRepository;
        }
    }
    境遇
  • タイプのNull値は
  • です.
  • タイプの空席が
  • の場合
  • タイプの複数の空
    -空の名前を試します.
    1.同じ名前の空が見つかった場合は、その空を使用します.
    2.同じ名前が見つからないと失敗する
  • 同じタイプの複数の空席の場合
  • @Primary
  • このタイプのすべてのアイドルタイプ
  • を受け入れる
  • @Qualifier(空の名前)
  • @Primary
  • @Repository @Primary
    public class MyBookRepository implements BookRepository{
    }
    @Repository 
    public class MyBookRepository2 implements BookRepository{
    }
    @Primary Anotation付きMyBook Repositoryを使用します.
  • このタイプのすべてのアイドルタイプ
  • を受け入れる
    @Service
    public class BookService {
        @Autowired
        List<BookRepository> bookRepositories;
        
            public void printBookRepository(
                this.bookRepositories.forEach(System.out::println);
        }
    }
  • @Qualifier(空の名前)
  • @Service
    public class BookService {
        @Autowired @Qualifier("myBookRepository")
        BookRepository BookRepository;
        
         public void printBookRepository(){
            System.out.println(bookRepository.getClass());
        }
    }
    または、フィールド名を表示し、フィールド名と同じタイプと名前の空を入力します.
    @Service
    public class BookService {
        @Autowired 
        BookRepository myBookRepository;
        
         public void printBookRepository(){
            System.out.println(mybookRepository.getClass());
        }
    }
    動作原理BeanPostProcessorというアイドルライフサイクルインタフェースによって処理される.空きライフサイクルでは、空きインスタンスを作成し、初期化中に(空きがある)ライフサイクル間のコールバックを処理し、そのインスタンスの前または後にbeanPostProcessorライフサイクルインタフェースを使用して新しく作成した空きインスタンスを変更できます.
    @Service
    public class BookService {
        @Autowired @Qualifier("myBookRepository")
        BookRepository myBookRepository;
    
        @PostConstruct
        public void setUp(){
            System.out.println(myBookRepository.getClass());
        }
    }
    @Service
    public class BookService implements InitializingBean {
        @Autowired @Qualifier("myBookRepository")
        BookRepository myBookRepository;
    
        @Override
        public void afterPropertiesSet() throws Exception {
        }
    }
    空の工場ライフサイクルインタフェースと方法
    https://velog.io/@jsj3282/IoC-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EC%99%80-ApplicationContext-BeanFactory
    さらに、springは、springが提供する@Autowiredおよび@Valueおよび@InjectのプレゼンテーションをAutowiredAnnotationBeanPostProcessor extends BeanPostProcessorを使用して処理することもできる.(P u n P o s t P o s t P o s s P o f o r einInitializationメソッドセクションで処理)
    検証方法
    @Component
    public class MyRunner implements ApplicationRunner {
    
        @Autowired
        ApplicationContext applicationContext;
    
        /*
        @Autowired
       AutowiredAnnotationBeanPostProcessor processor;
        */
        @Override
        public void run(ApplicationArguments args) throws Exception {
            AutowiredAnnotationBeanPostProcessor bean = applicationContext.getBean(AutowiredAnnotationBeanPostProcessor.class);
            System.out.println(bean);
        }
    }

    6.@Componentと構成部品スキャン

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Documented
    @Repeatable(ComponentScans.class)
    public @interface ComponentScan {
    
    	/**
    	 * Alias for {@link #basePackages}.
    	 * <p>Allows for more concise annotation declarations if no other attributes
    	 * are needed &mdash; for example, {@code @ComponentScan("org.my.pkg")}
    	 * instead of {@code @ComponentScan(basePackages = "org.my.pkg")}.
    	 */
    	@AliasFor("basePackages")
    	String[] value() default {};
    
    	/**
    	 * Base packages to scan for annotated components.
    	 * <p>{@link #value} is an alias for (and mutually exclusive with) this
    	 * attribute.
    	 * <p>Use {@link #basePackageClasses} for a type-safe alternative to
    	 * String-based package names.
    	 */
    	@AliasFor("value")
    	String[] basePackages() default {};
    
    	/**
    	 * Type-safe alternative to {@link #basePackages} for specifying the packages
    	 * to scan for annotated components. The package of each class specified will be scanned.
    	 * <p>Consider creating a special no-op marker class or interface in each package
    	 * that serves no purpose other than being referenced by this attribute.
    	 */
    	Class<?>[] basePackageClasses() default {};
    構成部品スキャンのキー機能
  • スキャン位置
  • を設定する.
  • フィルタ:スキャンまたはスキャンしないノイズ
  • @Component
  • @Repository
  • @Service
  • @Controller
  • @Configuration
  • @Component Anotationに付属する空は基本的にシングルポイントスキャンなので、実行時に空が生成されます.そのため、実行に時間がかかる場合があります.
    スプリングの実行時間を短縮したい場合->スプリング5から導入されたギャップを使用して空の登録を行う場合(反射やcglibなどのエージェントは使用しないため)
    public static void main(String[] args) { 
        new SpringApplicationBuilder() 
            .sources(Demospring51Application.class) 
            .initializers((ApplicationContextInitializer<GenericApplicationContext>) applicationContext -> { 
                applicationContext.registerBean(MyBean.class); 
            }) 
            .run(args); 
     }
    @SpringBootApplication
    public class Springtest2Application {
    
        public static void main(String[] args) {
    //        SpringApplication.run(Springtest2Application.class, args);
            var app = new SpringApplication(Springtest2Application.class);
            
            app.addInitializers(new ApplicationContextInitializer<GenericApplicationContext>() {
                @Override
                public void initialize(GenericApplicationContext ctx) {
                    ctx.registerBean(MyService.class); // 컴포넌트 스캔 밖에 있는 클래스 빈으로 등록
                }
            });
        }
    }
    @SpringBootApplication
    public class Springtest2Application {
    
       @Autowired
       MyService myService;
        
        public static void main(String[] args) {
    //        SpringApplication.run(Springtest2Application.class, args);
            var app = new SpringApplication(Springtest2Application.class);
            
            app.addInitializers((ApplicationContextInitializer<GenericApplicationContext>) ctx -> {
                ctx.registerBean(MyService.class); // 컴포넌트 스캔 밖에 있는 클래스 빈으로 등록
        }
    }
    あるいは、機能インタフェースを使用してもよい.
    @SpringBootApplication
    public class Springtest2Application {
    
        @Autowired
        MyService myService;
    
        public static void main(String[] args) {
    //        SpringApplication.run(Springtest2Application.class, args);
            var app = new SpringApplication(Springtest2Application.class);
            /*
            app.addInitializers(new ApplicationContextInitializer<GenericApplicationContext>() {
                @Override
                public void initialize(GenericApplicationContext ctx) {
                    ctx.registerBean(MyService.class);
                }
            });
            */
    
            app.addInitializers((ApplicationContextInitializer<GenericApplicationContext>) ctx -> {
                ctx.registerBean(MyService.class);
                ctx.registerBean(ApplicationRunner.class, () -> args1 -> System.out.println("Functional Bean Definition!!"));
    //            ctx.registerBean(ApplicationRunner.class, new Supplier<ApplicationRunner>() {
    //                @Override
    //                public ApplicationRunner get() {
    //                    return args1 -> System.out.println("Functinal Bean Definition!!");
    //                }
    //                @Override
    //                public ApplicationRunner get() {
    //                    return new ApplicationRunner() {
    //                        @Override
    //                        public void run(ApplicationArguments args) throws Exception {
    //                            System.out.println("Functional Bean Definiton!!");
    //                        }
    //                    };
    //                }
    //            });
            });
            app.run(args);
        }
    }
    @ComponentScanがパンクを使用して1つ1つ空の登録を放棄するよりも、@Configuration+@Beanで登録した@Beanを使用します.
    動作原理
  • @ComponentScanは、スキャンするパッケージおよびプレゼンテーションに関する情報
  • を提供します.
  • 実際のスキャンは、ClassPostProcessor beanFactory PostProcessorの構成によって処理される.
  • BEANFactoryPostProcessorは、他のすべての空を作成する前に適用されます.すなわち、他のすべての空を作成する前に、構成部品のスキャンを行い、適用します.

    7.空鏡


    スキャン
  • 単トン(Default)
  • プロトタイプ
    - Request
    - Session
    - WebSocket
    - ...
  • 原型貧が単色貧を参照すれば?
  • に問題はありません.
  • @Component @Scope(value = "prototype")
    public class Proto {
    
        @Autowired
        Single single;
    }
    
    単音位が原型位を参照すると?
    @Component
    public class Single {
    
        @Autowired
        private Proto proto;
    
        public Proto getProto() {
            return proto;
        }
    }
  • 原型彬は更新できませんか?
  • を更新するには、次の手順に従います.
    - scoped-proxy
    - Object-Provider
    -プロバイダ(標準)
  • @Component @Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS) 
    public class Proto {
    
        @Autowired
        Single single;
    }
    cglibraryというサードパーティ製ツールを使用して、クラスベースのエージェントを作成します.もともとJavaはインタフェースベースのエージェントしか作成できませんでした.Proxyも同じタイプなので注入できます.

    また、proxyを使う以外にも、他の方法があります.
    @Component
    public class Single {
    
        @Autowired
        private ObjectProvider<Proto> proto;
    
        public Proto getProto() {
            return proto.getIfAvailable();
        }
    }
    モノトーンオブジェクトを使用する際の注意点
  • はプロパティによって共有されています.
  • アプリケーションコンテキストの初期起動時にインスタンスを作成します.
  • @Component
    public class Single {
    
        @Autowired
        private Proto proto;
    
        // 쓰레드 세이프하다고 보장받을 수 없음(공유되는 bean)
        int value = 0;
        
        public Proto getProto() {
            return proto;
        }
    }
    リファレンス
  • インフラストラクチャ:スプリングフレームキーテクノロジー(白旗線)
  • https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/config/BeanPostProcessor.html
  • https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/ConfigurationClassPostProcessor.html
  • https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/config/BeanFactoryPostProcessor.html
  • https://en.wikipedia.org/wiki/Proxy_pattern