Spring IoC容器详解
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最佳实践
- 使用构造函数注入保证不可变性
- 合理使用@Qualifier指定Bean
- 使用@Lazy延迟初始化
- 利用@Profile区分环境配置
- 使用@Conditional条件化Bean
总结
Spring IoC容器是Spring框架的核心。深入理解Bean的装配、生命周期和作用域,能帮助你更好地使用Spring框架。