← 返回首页

Spring IoC容器详解

📂 java ⏱ 3 min 407 words

IoC容器原理

IoC(Inversion of Control)控制反转,将对象的创建和依赖管理交给容器负责。

BeanFactory

import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class BeanFactoryDemo {
    public static void main(String[] args) {
        ClassPathResource resource = new ClassPathResource("beans.xml");
        XmlBeanFactory factory = new XmlBeanFactory(resource);

        UserService userService = (UserService) factory.getBean("userService");
        System.out.println("BeanFactory获取Bean: " + userService);
    }
}

ApplicationContext

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ApplicationContextDemo {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context =
            new AnnotationConfigApplicationContext(AppConfig.class);

        UserService userService = context.getBean(UserService.class);
        System.out.println("ApplicationContext获取Bean: " + userService);

        System.out.println("Bean是否单例: " +
            (context.getBean("userService") == context.getBean("userService")));

        context.close();
    }
}

Bean定义

<?xml version="1.0" encoding="UTF-8"?>
<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
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource"
          scope="singleton" lazy-init="false"
          init-method="init" destroy-method="close">
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mydb"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>

    <bean id="userDao" class="com.example.dao.UserDaoImpl">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

自动装配

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class AutoWiringDemo {
    @Autowired
    private UserRepository userRepository;

    @Autowired
    @Qualifier("emailService")
    private NotificationService notificationService;

    public void process() {
        userRepository.save(new User());
        notificationService.send("Hello");
    }
}

Bean作用域详解

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.web.context.annotation.RequestScope;
import org.springframework.web.context.annotation.SessionScope;

@Configuration
public class BeanScopeConfig {
    @Bean
    public PrototypeBean prototypeBean() {
        return new PrototypeBean();
    }

    @Bean
    @Scope("singleton")
    public SingletonBean singletonBean() {
        return new SingletonBean();
    }
}

Bean生命周期回调

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

@Component
public class LifecycleBean implements InitializingBean, DisposableBean {
    @PostConstruct
    public void postConstruct() {
        System.out.println("PostConstruct回调");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean回调");
    }

    @PreDestroy
    public void preDestroy() {
        System.out.println("PreDestroy回调");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean回调");
    }
}

FactoryBean

import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;

@Component
public class MyFactoryBean implements FactoryBean<MyObject> {
    @Override
    public MyObject getObject() throws Exception {
        return new MyObject("工厂创建的对象");
    }

    @Override
    public Class<?> getObjectType() {
        return MyObject.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

条件Bean

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ConditionalConfig {
    @Bean
    @Conditional(OnLinuxCondition.class)
    public LinuxCommand linuxCommand() {
        return new LinuxCommand();
    }

    @Bean
    @Conditional(OnWindowsCondition.class)
    public WindowsCommand windowsCommand() {
        return new WindowsCommand();
    }
}

Profile配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

@Configuration
public class ProfileConfig {
    @Bean
    @Profile("dev")
    public DataSource devDataSource() {
        return new HikariDataSource(/* 开发环境配置 */);
    }

    @Bean
    @Profile("prod")
    public DataSource prodDataSource() {
        return new HikariDataSource(/* 生产环境配置 */);
    }
}

@Import注解

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import({DatabaseConfig.class, SecurityConfig.class})
public class AppConfig {
}

Spring容器刷新

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ContextRefreshDemo {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context =
            new AnnotationConfigApplicationContext();

        context.register(AppConfig.class);
        context.refresh();

        System.out.println("容器已刷新");

        UserService userService = context.getBean(UserService.class);
        System.out.println("UserService: " + userService);

        context.registerShutdownHook();
    }
}

IoC最佳实践

  1. 使用构造函数注入保证不可变性
  2. 合理使用@Qualifier指定Bean
  3. 使用@Lazy延迟初始化
  4. 利用@Profile区分环境配置
  5. 使用@Conditional条件化Bean

总结

Spring IoC容器是Spring框架的核心。深入理解Bean的装配、生命周期和作用域,能帮助你更好地使用Spring框架。