【附录】举例说明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对象工厂就像一个智能的"管家",帮你处理所有对象的创建、配置和管理工作,让你专注于业务逻辑的开发。

相关推荐
dylan_QAQ1 小时前
【附录】BeanFactoryPostProcessor的作用时机与核心实现?
后端·spring
it自2 小时前
SpringMVC在前后端分离架构中的执行流程详解
java·spring boot·后端·spring·架构
dylan_QAQ2 小时前
【附录】在spring中BeanDefinition 来源是由哪些?如何理解 BeanDefinition ,他在spring中起到了什么作用?
后端·spring
dylan_QAQ2 小时前
Spring 容器详解
后端·spring
dylan_QAQ3 小时前
【附录】为什么说BeanFactory和ApplicationContext是Spring容器?
spring
斜月3 小时前
Spring 自动装配原理即IOC创建流程
spring boot·后端·spring
半部论语4 小时前
Spring **${}** vs **#{}** 语法全景图
java·数据库·spring boot·后端·spring
知行合一。。。4 小时前
Spring--04--2--AOP自定义注解,数据过滤处理
java·后端·spring
dylan_QAQ5 小时前
Spring 事件机制详解
spring