Spring-iocソースコード分析
概要: Springはiocコンテナです。iocは、オブジェクト間の依存関係を管理のためにSpringに渡すことを意味します。たとえば、構成ファイルまたはJava構成クラスでさまざまなBean関係を定義し、SpringはこれらのBeanのロードを担当します。クラス間は維持されます。Beanを使用する必要がある場合は、getBeanを直接取得します。これは、IocコンテナとしてのSpringの主な機能です。
1つ、クラス紹介
1.ApplicationContextの概要
iocの原理を分析するために、タッチできるapplicationContentクラスから始めます。以下はスタートアップコードです。
ApplicationContext context = new ClassPathXmlApplicationContext(xmlPath)。
上記のコードは、構成ファイルを使用してSpringコンテナーを開始できます。このコードは、構成ファイルからSpringコンテナーにBeanをロードするためのものです。ClassPathXmlApplicationContextに加えて、AnnotationConfigApplicationContext(java構成)およびFileSystemXmlApplicationContext(ClassPathXmlと同様)もあります。
まず、ApplicationContextのクラス構造を見てみましょう。使用した実装クラスは、主にClassPathXmlApplicationContextとAnnotationConfigApplicationContextです。
ApplicationContextの
ConfigurableApplicationContext
AbstractApplicationContext
AbstractRefreshableApplicationContext GenericApplicationContext
AnnotationConfigApplicationContext
AbstractRefreshableConfigApplicationContext
AbstractXmlApplicationContext
ClassPathXmlApplicationContext
2.BeanFactoryの紹介
BeanFactoryインターフェースについて話しているのですが、BeanFactoryはBeanを提供するインターフェースであり、そのサブインターフェースはこれに基づいて拡張関数を追加します。上記のApplicationContextもBeanFactoryインターフェースを実装しますが、これはBeanのロードを実際に担当する別の実装です。 。クラスDefaultListableBeanFactoryは、Beanの解析と登録を完了します。// DefaultListableBeanFactoryタイプのプロパティは、AbstractRefreshableConfigApplicationContextから見つけることができます。
BeanFactory(ApplicationContextシリーズには、BeanFactoryを実装する多くのクラスまたはインターフェイスもあります)
AutowireCapableBeanFactory HierarchicalBeanFactory ListableBeanFactory
ConfigurableListableBeanFactory //上記の3つのインターフェイスを継承します
DefaultListableBeanFactory // ConfigurableListableBeanFactoryとBeanDefinitionRegistryを実装します(beanDefinitionの登録を担当します)
3.BeanDefinitionの紹介
BeanDefinitionを導入すると、DefaultListableBeanFactoryがBeanDefinitionRegistryインターフェース関数を実装してBeanをロードおよび登録することがわかります。
まず、DefaultListableBeanFactoryが作成されたBeanを格納し、いくつかのメンバー変数をインターセプトするために使用するものを見てみましょう。beanDefinitionMapはBeanDefinition情報を格納するためのものです。
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
BeanDefinitionは、Beanの名前、Beanのタイプ、依存するクラス、シングルトンかどうかなどを保存します。
2.プロセス分析
1.バックボーンメソッドを更新します
ClassPathXmlApplicationContextは主にrefreshメソッドを呼び出しますが、refresh()メソッドで呼び出されるメソッドは他にもたくさんあります。詳細については以下を参照してください。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
// 标记1---加载bean配置以及注册
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
// 标记2--- 初始化所有的 singleton beans
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}
}
}
上記のマーク1メソッド関数は、BeanDefinitionをコンテナーにロードする方法を示し、マーク2メソッドは、Beanを作成して初期化する方法を示し、その他はいくつかの補助的な処理関数です。
まず、これらの補助メソッドの主な機能を見てみましょう。
prepareBeanFactory:デフォルトのBeanPostProcessorを登録して、いくつかの関数を実装します。
invokeBeanFactoryPostProcessors:BeanFactoryPostProcessorのさまざまな実装クラスのメソッドを実行します。
registerBeanPostProcessors:BeanPostProcessorの実装クラスを登録します。このメソッドは、ここでは初期化されていない初期化の前後のBeanを拡張します。
2.GetFreshBeanFactory--登録済みBeanをロードします
リフレッシュの一般的な処理のいくつかを紹介した後、リフレッシュの開始点メソッドであるgetFreshBeanFactoryを見て、SpringがさまざまなBeanを構成ファイルから内部のDefaultListableBeanFactoryにロードする方法を見てみましょう。
getFreshBeanFactoryは、実際にはgetfreshBeanFactoryメソッドを呼び出します。
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {// ... }
try {
// 创建了DefaultListableBeanFactory,下面设置成this.beanFactory赋值
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
// 实际加载方法
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
}
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
上記から、refreshBeanFactoryが登録済みBeanをロードするためのDefaultListableBeanFactoryを作成することがわかります。
loadBeanDefinitionsシリーズのコールスタック。特定の実装は複雑すぎます。主なことは、構成されたBeanをDefaultListableBeanFactoryにロードすることです。(フォローアップサプリメント)
3. FinishBeanFactoryInitialization --- Beanを作成し、Beanを初期化します
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// ....
beanFactory.setTempClassLoader(null);
// 允许缓存元数据,即以后不会变更
beanFactory.freezeConfiguration();
// 实例化所有此时没有实例的单例bean 【主要调用方法】
beanFactory.preInstantiateSingletons();
}
上記のコードからわかるように、finishBeanFactoryInitializationは、実際にはDefaultListableBeanFactoryのpreInstantiateSingletonsメソッドを呼び出します。
public void preInstantiateSingletons() throws BeansException {
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
for (String beanName : beanNames) {
// 得到的BeanDefinition加工成RootBeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 不是抽象方法不是懒加载和多例
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
// ....
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else { // 创建bean的核心方法
getBean(beanName);
}
}
}
// ....略
}
上記からわかるように、シングルトンのみが遅延ロードされず、複数のインスタンスが実行されて 'Beanメソッドが取得され、このメソッドはdoGetBeanを呼び出します。このメソッドは非常に長いです。
protected <T> T doGetBean(final String name, final Class<T> requiredType, finalObject[] args, boolean typeCheckOnly)throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// 缓存中取
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// 父工厂取
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException(""); //循环依赖了
}
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean); // 依赖执行注册和getBean
}
}
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
// 创建bean 核心调用方法
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// 多例略....
}
else {
// 其他略....
}
}
}
// ....
return (T) bean;
}
doGetBeanメソッドは、削除後もまだ非常に長いです。これには主に、キャッシュからのフェッチ、親コンテナーが存在する場合はそのコンテナーからの戻り、見つかった場合の戻り、BeanDefinition内の依存Beanの判断、および依存関係の登録が含まれます。依存関係、およびgetBean()の同じ実行は、すべての依存Beanを再帰的に呼び出し、一連のgetBeanメソッドを実行することと同じです。最後に、依存関係が作成され、現在のBeanが作成され、createBeanメソッドが実行されます。実際の呼び出しはdoCreateBeanです。
doCreateBeanのコードは比較的長く、主要なものだけが投稿されています。
Object exposedObject = bean;
try {
填充属性
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
初始化,包含BeanPostProcess的前置和后置处理
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 各种awre的执行
invokeAwareMethods(beanName, bean);
if (mbd == null || !mbd.isSynthetic()) {
// 其他BeanPostProcess对本Bean的前置处理
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName);
}
try {
// 初始化方法执行
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
// ...
}
if (mbd == null || !mbd.isSynthetic()) {
// 其他BeanPostProcess对本Bean的后置处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
initializeBeanメソッドから、SpringでのBeanの作成プロセスのいくつかのAware、BeanPostProcess、InitMethod、およびその他のライフサイクルメソッドがこのメソッドに反映されていることがわかります。詳細については、以下を参照してください。https://blog.csdn.net/shuixiou1/article/details/79682954// あらゆる種類の初期化メソッドの混乱を引き起こす
これまで、SpringIOC関連のコードとSpringコンテナのメインインターフェイスクラスが導入されてきました。いくつかの例を自分で作成し、デバッグと組み合わせてブレークポイントを表示できます。