【附录】举例说明Spring是如何进行 创建、配置和管理 对象的呢?
此文是【Spring 容器详解】的支节点。
Spring对象工厂(容器)就像一个智能的"对象制造厂",它负责:
- 创建 - 根据配置创建你需要的对象
- 配置 - 设置对象的属性和依赖关系
- 管理 - 控制对象的生命周期和使用
1. 对象的创建
传统方式 vs Spring方式
传统方式 - 手动创建对象:
java
// 传统方式:每个对象都需要手动创建
public class UserService {
public void registerUser(User user) {
// 手动创建所有需要的对象
UserDao userDao = new UserDaoImpl();
EmailService emailService = new EmailServiceImpl();
LogService logService = new LogServiceImpl();
// 手动设置依赖关系
emailService.setLogService(logService);
// 执行业务逻辑
userDao.save(user);
emailService.sendWelcomeEmail(user);
logService.log("用户注册: " + user.getUsername());
}
}
Spring方式 - 工厂自动创建:
java
// Spring方式:工厂自动创建对象
@Service
public class UserService {
@Autowired
private UserDao userDao; // 工厂自动创建并注入
@Autowired
private EmailService emailService; // 工厂自动创建并注入
@Autowired
private LogService logService; // 工厂自动创建并注入
public void registerUser(User user) {
// 直接使用,工厂已经创建好了
userDao.save(user);
emailService.sendWelcomeEmail(user);
logService.log("用户注册: " + user.getUsername());
}
}
创建过程详解
1. 扫描和识别
java
// Spring扫描到这些注解,知道需要创建这些对象
@Component
public class UserDaoImpl implements UserDao {
// 实现代码
}
@Service
public class EmailServiceImpl implements EmailService {
// 实现代码
}
@Component
public class LogServiceImpl implements LogService {
// 实现代码
}
2. 创建BeanDefinition
java
// Spring内部为每个类创建BeanDefinition
BeanDefinition userDaoDef = new BeanDefinition();
userDaoDef.setBeanClassName("com.example.UserDaoImpl");
userDaoDef.setScope("singleton"); // 单例模式
BeanDefinition emailServiceDef = new BeanDefinition();
emailServiceDef.setBeanClassName("com.example.EmailServiceImpl");
emailServiceDef.setScope("singleton");
3. 实例化对象
java
// Spring使用反射创建对象
Class<?> clazz = Class.forName("com.example.UserDaoImpl");
Object userDao = clazz.newInstance(); // 创建UserDaoImpl实例
Class<?> emailServiceClass = Class.forName("com.example.EmailServiceImpl");
Object emailService = emailServiceClass.newInstance(); // 创建EmailServiceImpl实例
2. 对象的配置
属性配置
传统方式 - 硬编码配置:
java
public class DatabaseConfig {
private String url = "jdbc:mysql://localhost:3306/test";
private String username = "root";
private String password = "123456";
private int maxConnections = 10;
public Connection getConnection() {
// 使用硬编码的配置
return DriverManager.getConnection(url, username, password);
}
}
Spring方式 - 外部配置:
java
@Component
public class DatabaseConfig {
@Value("${database.url}")
private String url;
@Value("${database.username}")
private String username;
@Value("${database.password}")
private String password;
@Value("${database.maxConnections:10}")
private int maxConnections;
public Connection getConnection() {
return DriverManager.getConnection(url, username, password);
}
}
// application.properties
database.url=jdbc:mysql://localhost:3306/test
database.username=root
database.password=123456
database.maxConnections=20
依赖配置
传统方式 - 手动设置依赖:
java
public class UserService {
private UserDao userDao;
private EmailService emailService;
public UserService() {
// 手动创建依赖对象
this.userDao = new UserDaoImpl();
this.emailService = new EmailServiceImpl();
// 手动设置依赖关系
if (emailService instanceof EmailServiceImpl) {
((EmailServiceImpl) emailService).setUserDao(userDao);
}
}
}
Spring方式 - 自动注入依赖:
java
@Service
public class UserService {
@Autowired
private UserDao userDao; // Spring自动注入
@Autowired
private EmailService emailService; // Spring自动注入
// 或者使用构造器注入
public UserService(UserDao userDao, EmailService emailService) {
this.userDao = userDao;
this.emailService = emailService;
}
}
@Service
public class EmailServiceImpl implements EmailService {
@Autowired
private UserDao userDao; // Spring自动注入UserDao
public void sendWelcomeEmail(User user) {
// 使用注入的userDao
User savedUser = userDao.findById(user.getId());
// 发送邮件逻辑
}
}
配置类方式
java
@Configuration
public class AppConfig {
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("123456");
return dataSource;
}
@Bean
public UserDao userDao(DataSource dataSource) {
// Spring自动注入dataSource
return new UserDaoImpl(dataSource);
}
@Bean
public EmailService emailService(UserDao userDao) {
// Spring自动注入userDao
EmailServiceImpl emailService = new EmailServiceImpl();
emailService.setUserDao(userDao);
return emailService;
}
}
3. 对象的管理
生命周期管理
1. 创建阶段
java
@Component
public class UserService {
// 1. 构造器调用
public UserService() {
System.out.println("UserService构造器被调用");
}
// 2. 属性注入
@Autowired
private UserDao userDao;
// 3. 初始化方法
@PostConstruct
public void init() {
System.out.println("UserService初始化完成");
}
// 4. 销毁方法
@PreDestroy
public void destroy() {
System.out.println("UserService即将销毁");
}
}
2. 作用域管理
java
@Component
@Scope("singleton") // 单例模式,整个应用只有一个实例
public class SingletonService {
// 所有地方使用的都是同一个实例
}
@Component
@Scope("prototype") // 原型模式,每次获取都创建新实例
public class PrototypeService {
// 每次获取都是新的实例
}
@Component
@Scope("request") // 请求作用域,每个HTTP请求一个实例
public class RequestService {
// 每个HTTP请求都有独立的实例
}
@Component
@Scope("session") // 会话作用域,每个用户会话一个实例
public class SessionService {
// 每个用户会话都有独立的实例
}
对象获取管理
1. 按名称获取
java
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// 按名称获取对象
UserService userService = (UserService) context.getBean("userService");
2. 按类型获取
java
// 按类型获取对象
UserService userService = context.getBean(UserService.class);
3. 按名称和类型获取
java
// 按名称和类型获取对象
UserService userService = context.getBean("userService", UserService.class);
依赖关系管理
1. 循环依赖处理
java
@Service
public class UserService {
@Autowired
private EmailService emailService; // 依赖EmailService
public void registerUser(User user) {
// 业务逻辑
emailService.sendWelcomeEmail(user);
}
}
@Service
public class EmailService {
@Autowired
private UserService userService; // 依赖UserService
public void sendWelcomeEmail(User user) {
// 发送邮件逻辑
}
}
// Spring通过三级缓存解决循环依赖问题
2. 条件化Bean管理
java
@Configuration
public class AppConfig {
@Bean
@ConditionalOnProperty(name = "app.feature.email", havingValue = "true")
public EmailService emailService() {
return new EmailServiceImpl();
}
@Bean
@ConditionalOnProperty(name = "app.feature.email", havingValue = "false")
public EmailService emailService() {
return new MockEmailService(); // 模拟邮件服务
}
}
实际应用示例
完整的用户注册系统
1. 实体类
java
public class User {
private Long id;
private String username;
private String email;
// getter和setter
}
2. 数据访问层
java
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void save(User user) {
String sql = "INSERT INTO users (username, email) VALUES (?, ?)";
jdbcTemplate.update(sql, user.getUsername(), user.getEmail());
}
public User findById(Long id) {
String sql = "SELECT * FROM users WHERE id = ?";
return jdbcTemplate.queryForObject(sql, new Object[]{id}, new UserRowMapper());
}
}
3. 邮件服务
java
@Service
public class EmailServiceImpl implements EmailService {
@Autowired
private JavaMailSender mailSender;
@Value("${app.email.from}")
private String fromEmail;
public void sendWelcomeEmail(User user) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(fromEmail);
message.setTo(user.getEmail());
message.setSubject("欢迎注册");
message.setText("欢迎 " + user.getUsername() + " 加入我们!");
mailSender.send(message);
}
}
4. 业务服务层
java
@Service
@Transactional
public class UserService {
@Autowired
private UserDao userDao;
@Autowired
private EmailService emailService;
@Autowired
private LogService logService;
public void registerUser(User user) {
// 1. 保存用户
userDao.save(user);
// 2. 发送欢迎邮件
emailService.sendWelcomeEmail(user);
// 3. 记录日志
logService.log("用户注册成功: " + user.getUsername());
// 4. 发布事件
applicationContext.publishEvent(new UserRegisteredEvent(this, user));
}
}
5. 配置类
java
@Configuration
@EnableTransactionManagement
public class AppConfig {
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("123456");
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
public JavaMailSender mailSender() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost("smtp.gmail.com");
mailSender.setPort(587);
mailSender.setUsername("your-email@gmail.com");
mailSender.setPassword("your-password");
Properties props = mailSender.getJavaMailProperties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
return mailSender;
}
}
6. 使用示例
java
public class Main {
public static void main(String[] args) {
// 1. 创建Spring容器
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// 2. 获取业务服务
UserService userService = context.getBean(UserService.class);
// 3. 使用服务
User user = new User();
user.setUsername("张三");
user.setEmail("zhangsan@example.com");
userService.registerUser(user);
// 4. 关闭容器
((AnnotationConfigApplicationContext) context).close();
}
}
总结
Spring对象工厂的创建、配置和管理过程:
创建过程
- 扫描 - 扫描注解,识别需要创建的对象
- 定义 - 为每个对象创建BeanDefinition
- 实例化 - 使用反射创建对象实例
- 注入 - 自动注入依赖关系
配置过程
- 属性配置 - 通过@Value注入外部配置
- 依赖配置 - 通过@Autowired自动注入依赖
- 配置类 - 通过@Configuration统一管理配置
管理过程
- 生命周期 - 管理对象的创建、初始化、销毁
- 作用域 - 控制对象的创建策略(单例、原型等)
- 依赖关系 - 处理复杂的依赖关系,包括循环依赖
Spring对象工厂就像一个智能的"管家",帮你处理所有对象的创建、配置和管理工作,让你专注于业务逻辑的开发。