しかし、知識の概要をいくつかの基本的なコア:
必要が@Configurationを追加する際の春ブートプロジェクトが開始し、@ComponentScan
サードパーティのjarパッケージ@Bean @Configuration +は容器に注ぎました。OKの@ComponentSscanと同様@Controller内部ダイレクト@Service
@Scope実施形態では、単一達成することができます
飢えた男を作成するための呼び出しのデフォルトの開始時刻は、作成するときに呼び出している(ただし、時間、プロジェクトの開始時間を消費する)、他のです
コンポーネントを制御する必要がある構成要素を除く利用@ComponentScan排除、
上記プラス@ComponentScan Configクラスおよび他の注釈の注入を制御します
マルチ利用条件レジスタ・ビーン@Conditionオブジェクト、環境に応じてjuez決定
サードパーティ製の@import急速注入は、Beanオブジェクト
オープンのSpringBoot Emablexxx原則
ベースのImportBeanDefinitionRegister登録豆
登録BeanオブジェクトベースのFactoryBeanの
Springの拡張インターフェイス:条件
ビーン後の制御のために、一定の条件がコンテナに登録することを許可することができます満たしています。
ちょうどそれのようなシステムエンティティを記述します。
パブリック クラスOS { プライベート文字列名; プライベート整数バージョン。 パブリックOS(){ } @Override パブリック文字列のtoString(){ リターン "ハロー********************* OS {" + "NAME = '" +名+ '\'」+ "バージョン=" +バージョン+ '}' 。 } }
プロファイル(等価XML)
@Configuration パブリック クラスのMyConfig { @Bean @Conditional(MyCondition。クラス) パブリックOSのOS(){ System.out.printlnは( "ttttttttttttttttttttt" )。 返す 新しいOSを(); } }
制御された条件:
パブリック クラス MyCondition 実装条件条件の{ / ** * * @param conditionContext現在のコンテキストを取得する * @paramの詳細annotatedTypeMetadata現在の注釈を取得 * @return * / パブリック ブールマッチ(ConditionContext conditionContext、AnnotatedTypeMetadata annotatedTypeMetadata){ 環境環境は = conditionContext.getEnvironment( ); 文字列OSNAME = environment.getProperty( "os.name" ); IF(osName.equals( "Windowsは7" )){ リターン falseに; } 場合(osName.equals( "Windowsの10" )){ 戻り 真。 } を返す 偽。 } }
テストカテゴリ:
パブリック クラスのテスト{ 公共 静的 ボイドメイン(文字列[]引数){ AnnotationConfigApplicationContextのApplicationContext = 新しい AnnotationConfigApplicationContext(のMyConfig。クラス)。 文字列[] beanDefinitionNames = applicationContext.getBeanDefinitionNames()。 用(文字列名:beanDefinitionNames){ System.out.printlnは(名前)。 } OS osTest =(OS)applicationContext.getBean( "OS" )。 System.out.println(osTest)。 } }
結果:
2. @importコメント
なぜそれ@import考えるために注釈を使うのか?
注意事項@Beanそれは何のシナリオですか?サインジャーを外にロードされました。30豆がある場合は、一つ一つがああ書くのは非常に面倒です
したがって、簡略化操作@import、外側パッケージがジャースプリングIOC容器に注入されます。@Beanに相当。Beanオブジェクトの登録@import、IDは、現在のクラスの完全なパスです。
Configurationクラス:
@Configuration @import(OS。クラス) パブリック クラスのMyConfig { }
試験方法:
パブリック クラスのテスト{ 公共 静的 ボイドメイン(文字列[]引数){ AnnotationConfigApplicationContextのApplicationContext = 新しい AnnotationConfigApplicationContext(のMyConfig。クラス)。 文字列[] beanDefinitionNames = applicationContext.getBeanDefinitionNames()。 用(文字列名:beanDefinitionNames){ System.out.printlnは(名前)。 } // インポート的特殊性 OS osTest =(OS)applicationContext.getBean( "com.toov5.config.beanTest.OS" )。 System.out.println(osTest)。 } }
@importと@Bean違い:
@Bean注册的bean的id是方法名称
@Import当前类完整地址
共同应用场景都是引用外部jar包。
3. @EnableXXX
开启某某功能。底层使用@Import注解实现的
底层调用的就是@Import注解
场景: 封装一个框架,把不支持springboot的,鼓捣成支持springboot的!
实体类:
public class PayEntity { }
注解:
/** * 启动时候加入该注解,开启功能,会将实体类注入到容器中 */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Import({PayEntity.class}) public @interface EnablePayEntity { }
启动:
@Configuration @EnablePayEntity public class MyConfig { }
测试:
public class test { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class); String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); for (String name : beanDefinitionNames){ System.out.println(name); } } }
结果:
补充下: 可以@Import多个 ”,“解决。
4. ImportSelector接口 (跟 @Import注解一样的,只不过这个是原生api罢了)
实体类1:
public class MemberEntity { }
实体类2:
public class PersonEntity { }
原生接口的实现:
public class MyImportSeletcor implements ImportSelector { /** * 注解信息 * @param annotationMetadata * @return */ @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { return new String[]{"com.toov5.config.beanTest.MemberEntity", "com.toov5.config.beanTest.PersonEntity"}; } }
启动类:
@Configuration @Import(MyImportSeletcor.class) public class MyConfig { }
测试类:
public class test { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class); String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); for (String name : beanDefinitionNames){ System.out.println(name); } } }
结果:
5. ImportBeanDefinitionRegister接口 手动往ioc 注入bean
Spring容器中 Bean的信息,都是由BeanDefinition描述的
可以看下:
各种方法,Bean的各种信息。
实体类:
public class PersonEntity { }
接口实现,手动注入实体类
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /** * 注解信息 * @param annotationMetadata * @param beanDefinitionRegistry */ @Override public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) { //手动注册到ioc容器中 RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(PersonEntity.class); //IOC源码里面肯定有这个的!!! 对象放到IOC容器中就叫注册 (底层是个map 线程安全的) beanDefinitionRegistry.registerBeanDefinition("personEntity", rootBeanDefinition); } }
启动类:
@Configuration @Import(MyImportBeanDefinitionRegistrar.class) public class MyConfig { }
测试类:
public class test { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class); String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); for (String name : beanDefinitionNames){ System.out.println(name); } } }
运行结果:
6. 基于FactoryBean
FactoryBean也可以用来注册Bean
启动方式千万万,随便使用:
实体类:
public class PersonEntity { }
FactoryBean:
public class MyFactoryBean implements FactoryBean<PersonEntity> { @Override public PersonEntity getObject() throws Exception { return new PersonEntity(); } @Override public Class<?> getObjectType() { return PersonEntity.class; } @Override public boolean isSingleton() { //默认情况下是true。单例 return true; } //往ioc容器中注入对象 }
启动类:
@Configuration public class MyConfig { @Bean public MyFactoryBean myFactoryBean(){ return new MyFactoryBean(); } }
测试类:
public class test { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class); PersonEntity personEntity1 = (PersonEntity)applicationContext.getBean("myFactoryBean"); PersonEntity personEntity2 = (PersonEntity)applicationContext.getBean("myFactoryBean"); System.out.println(personEntity1 == personEntity2); } }
自己写“抄”个注解玩玩
自定义一个注解:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Component public @interface toov5 { }
实体类:
@toov5 public class Hello { }
启动采用扫包的方式:扫包的范围
@Configuration @ComponentScan("com.toov5.config.beanTest.entity") public class MyConfig { }
测试:
public class test { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class); String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); for (String name : beanDefinitionNames){ System.out.println(name); } } }
测试结果:
小结: spring 注入bean到容器方式:
@Bean @Import ,一般用于外部的jar包
其他的 @Service @Repository 注入对象底层其实都一样,就是区分不同的场景。使用的时候需要@ComponentScan注解扫包
还有就是实现一系列相应的接口去实现注入Bean 的方式