spring4.0ソース分析━━(AbstractBeanDefinitionクラス)
8689 ワード
前回は解析xmlについてお話ししましたが、BeanDefinitionについては詳しくありません.AbstractBeanDefinitionはspringプロファイルbeanラベルの実装であり、このクラスを理解することが重要です.ソースコードは次のとおりです.
上の多くが見覚えがあるのではないでしょうか.その中のsingleton、prototypeなど.これらは実はプロファイルにbeanが持つことができる属性ですが、singletonとprototypeはscopeに対応しているだけで、autowireModeのデフォルトは自動アセンブリではなく、lazyinitはfalseです.もう1つのsyntheticは、合成を意味し、ユーザー構成はbeanがデフォルトでfalseであることを意味します.しかしspringが起動すると自分でいくつかのbeanを作成してコンテナに追加し(AOPの説明で詳しく説明します)、springの場合は一般的にtrueに設定されます.BeanDefinitionの2つの重要な属性はConstructorArgumentValueとMutablePropertyValueです.ここでspringにはデフォルトのコンストラクタによってbeanが作成されていることを知っています.ユーザーはコンストラクタを指定してbeanをインスタンス化することもできます.ここのConstructorArgumentValueは関数を構築するために使われています.ここでは、次のテストクラスコードの説明を参照します.
プロファイルxmlを読み込むとGenericBeanDefinitionクラスが作成され、AbstractBeanDefinitionが継承されます.そしてbeanDefinitiongetConstructorArgumentValues().addGenericArgumentValueは、コンストラクション関数へのパラメータ設定です.もちろん、ここではパラメータのインデックスの位置を指定する方法addIndexedArgumentValueを指定することもできます.インデックスは0から始まります.指定されていない場合は、コードの実行前後順とタイプで判断します.
MutablePropertyValuesは、インスタンス化されたプロパティの場合に使用されます.テストコードは次のとおりです.
このようにする場合、beanはデフォルトの無パラメトリック構造関数であり、標準的なjavabeanクラスである必要があります.すなわちsetメソッドは正しく、そうでなければエラーを報告します.
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
/**
* Constant for the default scope name: "", equivalent to singleton status
* but to be overridden from a parent bean definition (if applicable).
*/
public static final String SCOPE_DEFAULT = "";
/**
* Constant that indicates no autowiring at all.
* @see #setAutowireMode
*/
public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
/**
* Constant that indicates autowiring bean properties by name.
* @see #setAutowireMode
*/
public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
/**
* Constant that indicates autowiring bean properties by type.
* @see #setAutowireMode
*/
public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
/**
* Constant that indicates autowiring a constructor.
* @see #setAutowireMode
*/
public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
/**
* Constant that indicates determining an appropriate autowire strategy
* through introspection of the bean class.
* @see #setAutowireMode
* @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,
* use annotation-based autowiring for clearer demarcation of autowiring needs.
*/
@Deprecated
public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
/**
* Constant that indicates no dependency check at all.
* @see #setDependencyCheck
*/
public static final int DEPENDENCY_CHECK_NONE = 0;
/**
* Constant that indicates dependency checking for object references.
* @see #setDependencyCheck
*/
public static final int DEPENDENCY_CHECK_OBJECTS = 1;
/**
* Constant that indicates dependency checking for "simple" properties.
* @see #setDependencyCheck
* @see org.springframework.beans.BeanUtils#isSimpleProperty
*/
public static final int DEPENDENCY_CHECK_SIMPLE = 2;
/**
* Constant that indicates dependency checking for all properties
* (object references as well as "simple" properties).
* @see #setDependencyCheck
*/
public static final int DEPENDENCY_CHECK_ALL = 3;
private volatile Object beanClass;
private String scope = SCOPE_DEFAULT;
private boolean singleton = true;
private boolean prototype = false;
private boolean abstractFlag = false;
private boolean lazyInit = false;
private int autowireMode = AUTOWIRE_NO;
private int dependencyCheck = DEPENDENCY_CHECK_NONE;
private String[] dependsOn;
private boolean autowireCandidate = true;
private boolean primary = false;
private final Map<String, AutowireCandidateQualifier> qualifiers =
new LinkedHashMap<String, AutowireCandidateQualifier>(0);
private boolean nonPublicAccessAllowed = true;
private boolean lenientConstructorResolution = true;
private ConstructorArgumentValues constructorArgumentValues;
private MutablePropertyValues propertyValues;
private MethodOverrides methodOverrides = new MethodOverrides();
private String factoryBeanName;
private String factoryMethodName;
private String initMethodName;
private String destroyMethodName;
private boolean enforceInitMethod = true;
private boolean enforceDestroyMethod = true;
private boolean synthetic = false;
private int role = BeanDefinition.ROLE_APPLICATION;
private String description;
private Resource resource;
。。。。。。。。。
}
上の多くが見覚えがあるのではないでしょうか.その中のsingleton、prototypeなど.これらは実はプロファイルにbeanが持つことができる属性ですが、singletonとprototypeはscopeに対応しているだけで、autowireModeのデフォルトは自動アセンブリではなく、lazyinitはfalseです.もう1つのsyntheticは、合成を意味し、ユーザー構成はbeanがデフォルトでfalseであることを意味します.しかしspringが起動すると自分でいくつかのbeanを作成してコンテナに追加し(AOPの説明で詳しく説明します)、springの場合は一般的にtrueに設定されます.BeanDefinitionの2つの重要な属性はConstructorArgumentValueとMutablePropertyValueです.ここでspringにはデフォルトのコンストラクタによってbeanが作成されていることを知っています.ユーザーはコンストラクタを指定してbeanをインスタンス化することもできます.ここのConstructorArgumentValueは関数を構築するために使われています.ここでは、次のテストクラスコードの説明を参照します.
public class Model1 {
private int age;
private String sex;
private String name;
public void init(){
System.out.println("init");
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Model1(){
}
public Model1(int age, String sex, String name) {
super();
this.age = age;
this.sex = sex;
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Model1 [age=" + age + ", sex=" + sex + ", name=" + name + "]";
}
}
@Test
public void testSpringBeanDefinitionConstructorArgumentValues(){
AbstractBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(Model1.class);
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(new ConstructorArgumentValues.ValueHolder(21));
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(new ConstructorArgumentValues.ValueHolder("female"));
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(new ConstructorArgumentValues.ValueHolder("C++"));
RootBeanDefinition mbd = new RootBeanDefinition(beanDefinition);
mbd.setScope("prototype");
mbd.setInitMethodName("init");
BeanDefinitionRegistry reg=new DefaultListableBeanFactory();
reg.registerBeanDefinition("model", mbd);
BeanFactory factory=(BeanFactory)reg;
Model1 model1=(Model1)factory.getBean("model");
Model1 model2=(Model1)factory.getBean("model");
System.out.println(model1.getAge());
Assert.assertEquals(false, model1==model2);
}
プロファイルxmlを読み込むとGenericBeanDefinitionクラスが作成され、AbstractBeanDefinitionが継承されます.そしてbeanDefinitiongetConstructorArgumentValues().addGenericArgumentValueは、コンストラクション関数へのパラメータ設定です.もちろん、ここではパラメータのインデックスの位置を指定する方法addIndexedArgumentValueを指定することもできます.インデックスは0から始まります.指定されていない場合は、コードの実行前後順とタイプで判断します.
MutablePropertyValuesは、インスタンス化されたプロパティの場合に使用されます.テストコードは次のとおりです.
@Test
public void testSpringBeanDefinitionMutablePropertyValues(){
AbstractBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(Model1.class);
MutablePropertyValues properties=new MutablePropertyValues();
//
properties.add("age", 21);
properties.add("sex", "male");
properties.add("name", "java bean");
beanDefinition.setPropertyValues(properties);
RootBeanDefinition mbd = new RootBeanDefinition(beanDefinition);
mbd.setScope("singleton");
mbd.setInitMethodName("init");
BeanDefinitionRegistry reg=new DefaultListableBeanFactory();
// IOC Bean
reg.registerBeanDefinition("model", mbd);
BeanFactory factory=(BeanFactory)reg;
Model1 model1=(Model1)factory.getBean("model");
Model1 model2=(Model1)factory.getBean("model");
System.out.println(model1.getAge());
Assert.assertEquals(false, model1==model2);
}
このようにする場合、beanはデフォルトの無パラメトリック構造関数であり、標準的なjavabeanクラスである必要があります.すなわちsetメソッドは正しく、そうでなければエラーを報告します.