偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

講一講Spring框架中的控制反轉(zhuǎn)(IoC)

開發(fā) 前端
控制反轉(zhuǎn)(Inversion of Control,IoC)是一種軟件設(shè)計原則,它將傳統(tǒng)程序流程的控制權(quán)從應(yīng)用程序代碼轉(zhuǎn)移到了框架或容器中。在傳統(tǒng)編程中,對象負(fù)責(zé)創(chuàng)建和管理它所依賴的對象;而在IoC模式下,這種責(zé)任被反轉(zhuǎn)了——由外部容器負(fù)責(zé)創(chuàng)建和管理組件及其依賴關(guān)系。

一、 Ioc的概念

控制反轉(zhuǎn)(Inversion of Control,IoC)是一種軟件設(shè)計原則,它將傳統(tǒng)程序流程的控制權(quán)從應(yīng)用程序代碼轉(zhuǎn)移到了框架或容器中。在傳統(tǒng)編程中,對象負(fù)責(zé)創(chuàng)建和管理它所依賴的對象;而在IoC模式下,這種責(zé)任被反轉(zhuǎn)了——由外部容器負(fù)責(zé)創(chuàng)建和管理組件及其依賴關(guān)系。

依賴注入(Dependency Injection)是實現(xiàn)IoC的主要方式之一。Martin Fowler在其文章中將依賴注入與IoC容器視為同一概念的不同表述:

  • IoC:強(qiáng)調(diào)控制權(quán)的反轉(zhuǎn)
  • DI:強(qiáng)調(diào)依賴關(guān)系的注入方式

Spring框架同時實現(xiàn)了這兩種理念,通過DI機(jī)制來實現(xiàn)IoC容器。

好萊塢原則:

"Don't call us, we'll call you"——這一好萊塢原則很好地詮釋了IoC的思想。組件不再主動獲取依賴,而是被動等待容器注入所需依賴。

二、Spring IoC容器核心實現(xiàn)

2.1 Spring IoC容器的核心接口體系

// 基礎(chǔ)容器接口
public interface BeanFactory {
    Object getBean(String name) throws BeansException;
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;
    // 其他方法...
}


// 應(yīng)用上下文接口,擴(kuò)展了BeanFactory
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, 
    HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    // 擴(kuò)展方法...
}

2.2 容器啟動流程

Spring IoC容器的初始化過程:

  1. 資源定位:通過ResourceLoader定位配置文件
  2. 加載解析:將配置信息加載為BeanDefinition
  3. 注冊:將BeanDefinition注冊到BeanDefinitionRegistry
  4. 依賴注入:根據(jù)依賴關(guān)系實例化并注入Bean

詳細(xì)入口在refresh方法中;

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 1. 準(zhǔn)備刷新上下文
        prepareRefresh();


        // 2. 創(chuàng)建并配置BeanFactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();


        // 3. 準(zhǔn)備BeanFactory使用
        prepareBeanFactory(beanFactory);


        try {
            // 4. 后處理BeanFactory
            postProcessBeanFactory(beanFactory);


            // 5. 執(zhí)行BeanFactoryPostProcessor
            invokeBeanFactoryPostProcessors(beanFactory);


            // 6. 注冊BeanPostProcessor
            registerBeanPostProcessors(beanFactory);


            // 7. 初始化消息源
            initMessageSource();


            // 8. 初始化事件廣播器
            initApplicationEventMulticaster();


            // 9. 初始化特殊Bean
            onRefresh();


            // 10. 注冊監(jiān)聽器
            registerListeners();


            // 11. 完成BeanFactory初始化,實例化所有非延遲單例Bean
            finishBeanFactoryInitialization(beanFactory);


            // 12. 完成刷新
            finishRefresh();
        } catch (BeansException ex) {
            // 異常處理...
        }
    }
}

2.3 BeanDefinition解析

Spring將配置的Bean信息解析為BeanDefinition對象,包含:

  • 類名
  • 作用域(scope)
  • 構(gòu)造函數(shù)參數(shù)值
  • 屬性值
  • 初始化方法
  • 銷毀方法

使用示例:

// 方式1:使用 RootBeanDefinition
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClassName("com.example.MyBean");
beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);


// 方式2:使用 GenericBeanDefinition
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(MyBean.class);
beanDefinition.setLazyInit(true);


// 方式3:使用 BeanDefinitionBuilder (推薦)
BeanDefinitionBuilder builder = BeanDefinitionBuilder
    .rootBeanDefinition(MyBean.class)
    .setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    .setLazyInit(true);
BeanDefinition beanDefinition = builder.getBeanDefinition();
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();


// 注冊單個BeanDefinition
beanFactory.registerBeanDefinition("myBean", beanDefinition);


// 批量注冊
Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
beanDefinitionMap.put("serviceA", serviceABeanDefinition);
beanDefinitionMap.put("serviceB", serviceBBeanDefinition);
beanFactory.registerBeanDefinitions(beanDefinitionMap);

2.4 Bean生命周期管理

完整的Bean生命周期:

  • 實例化(Instantiation)
  • 屬性填充(Populate properties)
  • 設(shè)置BeanName(如果實現(xiàn)了BeanNameAware)
  • 設(shè)置BeanFactory(如果實現(xiàn)了BeanFactoryAware)
  • 前置初始化(BeanPostProcessor.postProcessBeforeInitialization)
  • 初始化(InitializingBean.afterPropertiesSet或自定義init-method)
  • 后置初始化(BeanPostProcessor.postProcessAfterInitialization)
  • 使用
  • 銷毀(Destroy)

圖示:

Bean實例化
    |
    v
屬性賦值(依賴注入)
    |
    v
Aware接口回調(diào)(BeanNameAware等)
    |
    v
BeanPostProcessor.postProcessBeforeInitialization()
    |
    v
@PostConstruct注解方法
    |
    v
InitializingBean.afterPropertiesSet()
    |
    v
自定義init-method
    |
    v
BeanPostProcessor.postProcessAfterInitialization()
    |
    v
Bean就緒可用
    |
    v
容器關(guān)閉時@PreDestroy注解方法
    |
    v
DisposableBean.destroy()
    |
    v
自定義destroy-method

2.5 循環(huán)依賴解決方案

Spring通過三級緩存解決循環(huán)依賴問題:

  • singletonObjects:一級緩存,存放完全初始化好的Bean
  • earlySingletonObjects:二級緩存,存放早期暴露的Bean(已實例化但未初始化)
  • singletonFactories:三級緩存,存放Bean工廠,用于生成早期引用

源碼分析:

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 1. 從一級緩存獲取
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            // 2. 從二級緩存獲取
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                // 3. 從三級緩存獲取ObjectFactory
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

2.6 Spring支持多種Bean作用域

  • singleton (默認(rèn)):每個容器一個實例
  • prototype:每次請求新實例
  • request:每個HTTP請求一個實例
  • session:每個HTTP會話一個實例
  • application:ServletContext生命周期

使用示例:

@Bean
@Scope("prototype")
public PrototypeBean prototypeBean() {
    return new PrototypeBean();
}

三、Spring IoC的使用

3.1 XML配置方式

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="userService" class="com.example.UserServiceImpl">
        <property name="userRepository" ref="userRepository"/>
    </bean>


    <bean id="userRepository" class="com.example.UserRepositoryImpl"/>
</beans>

使用容器

// 加載Spring配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");


// 獲取bean實例
UserService userService = (UserService) context.getBean("userService");

3.2 注解方式

@Configuration
public class AppConfig {


    @Bean
    public UserRepository userRepository() {
        return new UserRepositoryImpl();
    }


    @Bean
    public UserService userService(UserRepository userRepository) {
        return new UserServiceImpl(userRepository);
    }
}

使用容器

// 使用AnnotationConfigApplicationContext加載配置類
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);


// 獲取bean
UserService userService = context.getBean(UserService.class);

3.3 自動裝配方式

@Component
public class UserServiceImpl implements UserService {


    @Autowired  // 按類型自動裝配
    private UserRepository userRepository;


    // 構(gòu)造器注入(Spring 4.3+可以省略@Autowired)
    @Autowired
    public UserServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }


    // Setter注入
    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

核心注解:

  • @Component:標(biāo)識一個類為Spring組件
  • @Repository:標(biāo)識數(shù)據(jù)訪問層組件
  • @Service:標(biāo)識服務(wù)層組件
  • @Controller:標(biāo)識控制器層組件
  • @Autowired:自動裝配依賴

啟動注解掃描:

<!-- 在XML中開啟注解掃描 -->
<context:component-scan base-package="com.example"/>

@Configuration
@ComponentScan("com.example")
public class AppConfig {
    // 其他配置...
}

3.4 延遲初始化

<bean id="lazyBean" class="com.example.ExpensiveBean" lazy-init="true"/>
@Bean
@Lazy
public ExpensiveBean expensiveBean() {
    return new ExpensiveBean();
}

3.5 條件化裝配

@Bean
@Conditional(DataSourceAvailableCondition.class)
public DataSource dataSource() {
    // 僅當(dāng)條件滿足時創(chuàng)建DataSource
}

3.6 @Profile按環(huán)境注冊Bean

@Configuration
public class AppConfig {


    @Bean
    @Profile("dev")
    public DataSource devDataSource() {
        // 開發(fā)環(huán)境數(shù)據(jù)源
    }


    @Bean
    @Profile("prod")
    public DataSource prodDataSource() {
        // 生產(chǎn)環(huán)境數(shù)據(jù)源
    }
}

配置文件

spring:
  profiles:
    active: dev
責(zé)任編輯:武曉燕 來源: 全棧程序員老馬
相關(guān)推薦

2022-01-17 07:59:13

SpringSpringMVCSpringBoot

2009-06-22 10:20:01

Spring IoC容

2022-05-24 08:09:00

HadoopHiveSpark

2012-05-04 13:25:46

HTML5

2021-01-18 05:11:14

通信Nodejs進(jìn)程

2020-09-17 06:53:38

項目規(guī)范流程

2022-02-14 08:13:33

刪庫MySQL備份

2009-05-26 11:28:53

2021-07-28 08:32:58

Go并發(fā)Select

2012-07-02 15:26:19

Spring架構(gòu)框架

2025-06-30 01:33:00

2024-05-10 07:19:46

IOC依賴倒置控制反轉(zhuǎn)

2025-01-13 12:00:00

反射Java開發(fā)

2019-01-03 12:50:52

Spring BootJava編程語言

2022-04-30 08:50:11

控制反轉(zhuǎn)Spring依賴注入

2020-12-16 06:33:06

thisJava調(diào)用

2024-01-08 13:40:00

并發(fā)安全? 數(shù)量

2020-03-26 09:18:54

高薪本質(zhì)因素

2020-09-03 11:04:20

Spring 循環(huán)依賴

2022-08-10 07:06:57

IoCDISpring
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號