Springソース分析のIOCの3つの一般的な使い方とソース実現(一)
以下の4種類があります
(spring 4.xに精通したp 175より)
よく使われるのは上位3種です
第一の方法
public static void main( String[] args )
{
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
System.out.println(ctx.getBean("person"));
}
第2の方式
定義#テイギ#
@Service
public class UserServiceImpl {
public void test(){
System.out.println(666);
}
}
取得
@Autowired
private static UserServiceImpl userService;
第3の方法
定義#テイギ#
@Configuration
public class MainConfig {
@Bean
public Person person(){
return new Person();
}
}
注意:@Bean形式で使用する場合、beanのデフォルト名はメソッド名であり、Bean(value=「bean」の名前)ではbeanの名前が指定されます
コンテナからBeanの情報を読み込む(インポート構成クラス)
取得
public static void main( String[] args )
{
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class);
System.out.println(ctx.getBean("person"));
}
2.実現方法
1.Javaクラス構成に基づく実現方式ソース分析
1.この2つのコードを実行しました
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class);
System.out.println(ctx.getBean("person"));
まず、コンストラクタのソースコードを開きます.
public AnnotationConfigApplicationContext(Class>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
2.まず焦らないで、主役のA n o t i o n C o n f i g ApplicationContextそれは親がいて、クラスの初期化の順序の関係のため、先に親を初期化することができて、だから親を見なければならなくて、ずっと最後の親がDefaultResourceLoaderであることを見ています
DefaultResourceLoaderは、明らかにリソースをロードするために使用されています.最後から2番目のAbstractApplicationContextの非パラメトリック構造でも、ロードリソース関連を初期化します.
Ok、最後の親GenericApplicationContextを見てみましょう.親のデフォルト初期化では、次のパラメータなしを使用します.
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
ここではspringiocシステムを作成する上で重要なクラスであるD e f a t i o l t ListableBeanFactory、D e f a t i o l t LitableBeanFactoryは非常に重要であり、ioc関連の多くの機能を実現しており、私たちに提供できるAnnotationConfigApplicationContextの使用(後述)
3.ok親は全部読んでしまったので、主役のAnnotationConfigApplicationContextに戻ります.
コンストラクタがどのコード(自身に戻る)だったかを見てみましょう.
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
2行だけです.
4.まず最初のthisを見てください.reader = new AnnotatedBeanDefinitionReader(this);
入る
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
独自のコンストラクタを再び呼び出します
ここでは、getOrCreateEnvironment(registry)
この方法は名前からキャッシュの意味がわかるのは明らかで、取得または作成し、1回目であれば2回目であれば取得し、2回目で持つ1回目のキャッシュです.次のようになります.
private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry instanceof EnvironmentCapable) {
return ((EnvironmentCapable) registry).getEnvironment();
}
return new StandardEnvironment();
}
OK、見続けてください.さっきはコンストラクタから別のコンストラクタに行きました.
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
ConditionEvealuatorはconditonを計算する解析器(後述)であり、ここでは明らかに主な論理はAnnotationConfigUtilsである.registerAnnotationConfigProcessors(this.registry);
次は...registerAnnotationConfigProcessors(this.registry);重中の重さで、やっと大きな論理が始まりました!以前は色々な継承ジャンプでした!
registerAnnotationConfigProcessorsソースコードは以下のように実現される.
public static Set registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set beanDefs = new LinkedHashSet(4);
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
長いですね.まず第1部を見てください.
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
明らかにこれはregistryからD e f a ultListableBeanFactoryを取ったもので、前に主役のA n o t i o n C o f i g ApplicationContextの親GenericApplicationContextを覚えていますか?その無パラメトリック構造では、DefaultListableBeanFactoryが作成されます.今このregistryに持って行って、このregistryは前にthisで伝わってきた主役のA n o t i o n C o n f i g ApplicationContextが自然にDefaultListableBeanFactoryを持っています.後の論理はnull判定とコンパレータと解析器の設定です.
Set beanDefs = new LinkedHashSet(4);
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
BeanDefinitionHolderを保存するsetコレクションが作成されました(BeanDefinition Yes).後で非常に多くのif判断があります.これは何を判断しますか?
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
registryに定数定義のものが1つずつ存在するか否かを判断する.これらの定数は何ですか?開いてみると:
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
クラスのフルパスです.registryにない場合は、最後の文(前の文は最後の文にサービスされています):
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
つまり,このクラスがあるかどうかを判断し,ないかを判断してこのクラスを追加し,このクラスは構成注釈を解析するためのプロセッサである.
もう一つpublic static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor";
総合的に見ると、このコードの後半はspringがサポートする様々な注釈の解析器を登録する論理である.
この対応は自動アセンブリ注記を解析するために使用されます.
最後に、次のようになります.
public static Set registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, Object source) {
// DefaultListableBeanFactory, null
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set beanDefs = new LinkedHashSet(8);
// @Configuration bean (ConfigurationClassPostProcessor)
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// AutoWired bean
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// @Required
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// JSR250 , JSR250
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// jpa, jpa
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// @EventListener
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
// spring ( , ? registry , , registry DefaultListableBeanFactory !)
return beanDefs;
}
はい、以上の分析を終えて、主役のA n n o t i o n C o n f i g ApplicationContextに戻ります.
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
の分析の第1文はついにこのreaderを终えて、次に第2文を分析します.
名前はクラスパスの下のスキャナーであることがわかり、ソースコードの表示を開始します!
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
this(registry, true);
}
フォローを続ける
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}
最初のregistryは前に言ったDefaultListableBeanFactory伝のthis、2番目のtrue伝のどちらかで、デフォルトのfilterを使用するかどうか、はいを選択しました.3つ目は前に話しましたが、ある場合はない場合は作成し、キャッシュします.に続く
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, ResourceLoader resourceLoader) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
if (useDefaultFilters) {
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(resourceLoader);
}
このコードの前には、付与、デフォルトのfiltersの登録、registryから取得した環境設定の設定、最後にResourceLoaderの設定があります.
一部一部を見て、まずregisterDefaultFilters()を見ます.
/**
* Register the default filter for {@link Component @Component}.
* This will implicitly register all annotations that have the
* {@link Component @Component} meta-annotation including the
* {@link Repository @Repository}, {@link Service @Service}, and
* {@link Controller @Controller} stereotype annotations.
*
Also supports Java EE 6's {@link javax.annotation.ManagedBean} and
* JSR-330's {@link javax.inject.Named} annotations, if available.
*
*/
@SuppressWarnings("unchecked")
protected void registerDefaultFilters() {
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
}
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
メソッドコメントは、これらのデフォルトのfilterを登録すると、@Component、@Repository、@Controllerが機能します.
その後メソッド内部に注入するComponentを追加する.classが入ってきて、@Componentが効いて、@Repository、@Controller自体が打たれた@Componentはサブ注釈なので、それも連動して機能します
後部はjsr 250 330に関する注釈を判断する
ここまで読んで、上層階に戻って、ここまで
public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
super(beanFactory);
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
私たちも大体見終わったので、一つのコンストラクタを見終わった.大功を成し遂げた......もう、半分...このコンストラクタは無パラメータであることがわかりましたが、前に使用した2つのコードは次のとおりです.
AnnotationConfigApplicationContext annotationConfigApplication = new AnnotationConfigApplicationContext (MainConfig.class);Person person2 = (Person)annotationConfigApplication.getBean("person2");
中主役AnnotationConfigApplicationContext用のclass付きコンストラクタですね.
public AnnotationConfigApplicationContext(Class>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
ここが最初の2行のコードの最初の呼び出しです.私たちはこれを();見終わった!
2番目のregister(annotatedClasses)を見てみましょう.どんどんフォロー
public void register(Class>... annotatedClasses) {
Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
this.reader.register(annotatedClasses);
}
ここまで続く
public void registerBean(Class> annotatedClass, String name, Class extends Annotation>... qualifiers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
このコードは、転送された構成クラスのbeanをすべて登録したものです.これで二文目は終わります.最後の3番目のコアについては、次の文章に残しておきます.がんばって!