【附录】举例说明Spring是如何进行 创建、配置和管理 对象的呢?

【附录】举例说明Spring是如何进行 创建、配置和管理 对象的呢?

此文是【Spring 容器详解】的支节点。

Spring对象工厂(容器)就像一个智能的"对象制造厂",它负责:

  1. 创建 - 根据配置创建你需要的对象
  2. 配置 - 设置对象的属性和依赖关系
  3. 管理 - 控制对象的生命周期和使用

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对象工厂的创建、配置和管理过程:

创建过程

  1. 扫描 - 扫描注解,识别需要创建的对象
  2. 定义 - 为每个对象创建BeanDefinition
  3. 实例化 - 使用反射创建对象实例
  4. 注入 - 自动注入依赖关系

配置过程

  1. 属性配置 - 通过@Value注入外部配置
  2. 依赖配置 - 通过@Autowired自动注入依赖
  3. 配置类 - 通过@Configuration统一管理配置

管理过程

  1. 生命周期 - 管理对象的创建、初始化、销毁
  2. 作用域 - 控制对象的创建策略(单例、原型等)
  3. 依赖关系 - 处理复杂的依赖关系,包括循环依赖

Spring对象工厂就像一个智能的"管家",帮你处理所有对象的创建、配置和管理工作,让你专注于业务逻辑的开发。

相关推荐
Listen·Rain24 分钟前
向量化详解
java·人工智能·spring·机器学习·ai
添砖java_8572 小时前
网页聊天室测试报告
java·spring boot·spring·maven
xixingzhe23 小时前
Spring 依赖注入
java·后端·spring
闲猫12 小时前
Spring AI 对接Deepseek ChatModel 聊天对话
java·前端·spring
醇氧19 小时前
Spring 容器 Map 注入机制详解
java·后端·spring
ylscode19 小时前
Cloudflare Workers Cache 深度解析:边缘缓存如何重塑无服务器性能边界
java·spring·mybatis
沉静的小伙20 小时前
Spring事务
java·数据库·spring
Wang's Blog1 天前
Java框架快速入门: Spring Bean核心配置与实例化详解
java·开发语言·spring
爱敲代码的小鱼1 天前
springboot原理篇:
java·spring boot·spring
k↑1 天前
SpringCloud + React19 集成Scalar的API文档
后端·spring·spring cloud