Spring 02:注解驱动开发

引言

        在Spring框架中,IOC(控制反转)和DI(依赖注入)是核心思想。通过注解开发,我们可以大幅简化Spring配置,提高开发效率。本文将深入探讨Spring IOC/DI的注解开发模式,并结合实际案例展示如何管理第三方框架(如Mybatis和Junit)。

一、管理第三方Bean

为避免硬编码,将数据库配置提取到properties文件:

# jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db
jdbc.username=root
jdbc.password=root

(一)Durid

pom.xml中添加依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.16</version>
</dependency>

applicationContext.xml配置文件中添加DruidDataSource的配置

<?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">
    <!--管理DruidDataSource对象-->
    <bean class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
</beans>
  • driverClassName:数据库驱动
  • url:数据库连接地址
  • username:数据库连接用户名
  • password:数据库连接密码

setter注入数据库连接的四要素,要和自己使用的数据库信息一致。

(二)C3P0

pom.xml中添加依赖

<dependency>
    <groupId>c3p0</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.1.2</version>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>
  • DruidC3P0在没有导入mysql驱动包的前提下,一个没报错一个报错,说明Druid在初始化的 时候没有去加载驱动,而C3P0刚好相反
  • Druid程序运行虽然没有报错,但是当调用DruidDataSourcegetConnection()方法获取连 接的时候,也会报找不到驱动类的错误

配置第三方bean,通过setter方法注入ComboPooledDataSource

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_db"/>
    <property name="user" value="root"/>
    <property name="password" value="root"/>
    <property name="maxPoolSize" value="1000"/>
</bean>

(三)总结

 完成durid或C3P0后,从IOC容器中获取对应的bean对象,之后即可运行程序

public class App {
    public static void main(String[] args) {
        ApplicationContext ctx = new
        ClassPathXmlApplicationContext("applicationContext.xml");
        DataSource dataSource = (DataSource) ctx.getBean("dataSource");
        System.out.println(dataSource);
    }
}

Druid vs C3P0 对比

特性DruidC3P0
提供方阿里开源JDBC连接池
性能较低
驱动加载时机延迟加载(运行时)初始化时加载
监控功能强大的监控和统计功能基本功能

 二、加载Properties配置文件

Spring配置加载

<context:property-placeholder 
    location="classpath:jdbc.properties" 
    system-properties-mode="NEVER"/>

加载方式对比

  • 单个文件:location="jdbc.properties"

  • 多个文件:location="jdbc.properties,jdbc2.properties"

  • 通配符:location="*.properties"

  • 类路径:location="classpath:*.properties"

  • 类路径(含依赖):location="classpath*:*.properties"

三、Spring核心容器

        这里所说的核心容器,可以把它简单的理解为ApplicationContext。

(一)容器创建

传统 XML 配置容器

// 类路径加载(推荐)
ApplicationContext ctx = 
    new ClassPathXmlApplicationContext("applicationContext.xml");

// 文件系统加载(不推荐使用,当项目的位置发生变化后,代码也需要跟着改,耦合度较高)
ApplicationContext ctx = 
    new FileSystemXmlApplicationContext("D:/config/applicationContext.xml");

现代注解配置容器

AnnotationConfigApplicationContext是现代 Spring 应用开发中纯注解配置方式的核心入口,完全取代了传统的 XML 配置方式。 

// 加载配置类初始化容器
ApplicationContext ctx = 
    new AnnotationConfigApplicationContext(SpringConfig.class);
  • ClassPathXmlApplicationContext是加载XML配置文件
  • AnnotationConfigApplicationContext是加载配置类

 

(二)获取Bean的三种方式

// 1. 按名称获取(需强转)
BookDao dao = (BookDao) ctx.getBean("bookDao");

// 2. 按名称+类型获取(解决强转,但多一个参数)
BookDao dao = ctx.getBean("bookDao", BookDao.class);

// 3. 按类型获取(需确保IOC容器中该类型对应的bean对象只能有一个)
BookDao dao = ctx.getBean(BookDao.class);

(三)容器类层次结构

只需要知晓容器的最上级的父接口为BeanFactory即可

(四)BeanFactory

特性BeanFactoryApplicationContext
加载时机延迟加载(使用时创建)立即加载(启动时创建)
功能完整性基础功能扩展功能(AOP等)
使用场景资源受限环境大多数应用场景

(五)小结

  • BeanFactoryIoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载
  • ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载
  • ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展其功能
  • ApplicationContext接口常用初始化类
    • ClassPathXmlApplicationContext(常用)
    • FileSystemXmlApplicationContext

四、注解开发

(一)核心注解

特性@Component@Controller@Service@Repository
继承关系基础注解派生自@Component派生自@Component派生自@Component
使用场景通用组件MVC控制器业务逻辑层数据访问层
语义含义通用Spring组件处理用户请求业务逻辑服务数据存储库
特殊功能处理HTTP请求事务管理异常转换
层级位置任意层表现层业务层持久层
典型用途工具类、配置类REST控制器业务逻辑实现DAO实现类

虽然技术上可以全部使用@Component,但使用特定注解有利于明确标识组件在架构中的角色,提高代码可读性,方便针对特定层进行切面编程,以及进行如@Repository的异常转换功能。

  • 处理HTTP请求 → @Controller - 系统的"门面",处理用户交互

  • 实现业务逻辑 → @Service - 业务逻辑的"大脑",实现核心功能

  • 数据库访问 → @Repository - 数据访问的"手",与持久化存储交互

  • 通用工具类 → @Component - 通用的"工具",提供辅助功能

(二)纯注解配置

@Configuration
@ComponentScan("com.example")
@PropertySource("classpath:app.properties")
public class AppConfig {
}
特性@Configuration@ComponentScan
主要作用标识配置类自动扫描并注册组件
替代方案XML配置文件 (<beans>标签)XML组件扫描 (<context:component-scan>)
使用位置类级别类级别(常与@Configuration一起使用)
核心功能定义Bean和配置发现和管理组件
是否必须纯注解开发必须可选,但强烈推荐使用
典型使用场景定义第三方Bean、全局配置自动注册业务组件
  • ,@Configuration设置该类为spring配置类,使用类替换applicationContext.xml文件
    • value(默认):定义beanid
  • @ComponentScan设置spring配置类扫描路径,用于加载使用注解格式定义的bean
    • value(默认):扫描路径,此路径可以逐层向下扫描
    • 此注解只能添加一次,多个数据请用数组格式
    • @ComponentScan({com.example.service","com.example.dao"})

    (三)Bean作用域与生命周期

    @Repository
    @Scope("prototype") // 默认为singleton
    public class UserDaoImpl {
        
        @PostConstruct // 设置该方法为初始化方法
        public void init() {
            System.out.println("Bean初始化");
        }
        
        @PreDestroy  // 设置该方法为销毁方法
        public void destroy() {
            System.out.println("Bean销毁");
        }
    }
    名称
    @Scope
    类型
    类注解
    位置
    类定义上方
    作用
    设置该类创建对象的作用范围
    可用于设置创建出的bean是否为单例对象
    属性
    value(默认):定义bean作用范围,
    默认值singleton(单例),可选值prototype(非单例)

    xml属性与注解的关系大致如下:

    (四)依赖注入

    @Service
    public class UserServiceImpl {
        
        @Autowired // 按类型注入
        private UserDao userDao;
        
        @Autowired
        @Qualifier("mainDataSource") // 按名称注入
        private DataSource dataSource;
        
        @Value("${app.timeout}") // 注入简单值
        private int timeout;
    }
    注解名称类型应用位置主要作用关键属性
    @Autowired属性/方法/方法形参注解属性定义上方
    setter方法上方
    方法形参前面
    自动装配引用类型
    根据类型自动注入依赖对象
    required:是否必须注入
    (true/false,默认true)
    @Qualifier属性/方法注解属性定义上方
    setter方法上方
    精确指定Bean名称
    解决同类型多个Bean的歧义
    value:指定要注入的Bean ID
    @Value属性/方法注解属性定义上方
    setter方法上方
    注入简单类型值
    注入基本类型、字符串或表达式结果
    value:要注入的值或表达式
    (如 ${property})
    @PropertySource类注解类定义上方加载外部配置
    将properties文件加载到Spring环境
    value:配置文件名或数组
    (支持 classpath: 前缀)

    五、整合第三方框架

    (一) 管理第三方Bean

    @Configuration
    public class DataSourceConfig {
        
        @Bean
        public DataSource dataSource() {
            DruidDataSource ds = new DruidDataSource();
            ds.setDriverClassName("com.mysql.jdbc.Driver");
            // 其他配置...
            return ds;
        }
    }

    (二)整合Mybatis

    @Configuration
    public class MybatisConfig {
        
        @Bean
        public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
            SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
            factory.setDataSource(dataSource);
            factory.setTypeAliasesPackage("com.example.domain");
            return factory.getObject();
        }
    }

    (三)整合Junit

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = {AppConfig.class})
    public class UserServiceTest {
        
        @Autowired
        private UserService userService;
        
        @Test
        public void testFindUser() {
            User user = userService.findById(1);
            assertNotNull(user);
        }
    }
    注解应用位置主要作用关键属性适用场景
    @Bean配置类中的方法上显式声明 Spring Bean
    将方法返回对象注册为 Spring Bean
    name/value:Bean 名称
    initMethod:初始化方法
    destroyMethod:销毁方法
    管理第三方库组件
    复杂初始化逻辑
    条件化创建 Bean
    @Import配置类上模块化配置组合
    导入其他配置类或组件
    value:要导入的类数组
    (支持配置类、组件类、ImportSelector 等)
    大型应用配置拆分
    特性模块化
    自动配置机制
    @RunWithJUnit 测试类上指定测试运行器
    定制测试执行环境
    value:测试运行器类
    (如 SpringJUnit4ClassRunner
    Spring 集成测试
    需要容器环境的测试
    定制测试行为

    @Context

    Configuration

    JUnit 测试类上加载 Spring 配置
    为测试提供应用上下文
    classes:配置类数组
    locations:配置文件路径
    inheritLocations:继承配置
    单元测试依赖注入
    集成测试环境
    多配置组合测试

    六、总结

    功能XML配置注解
    定义Bean<bean>@Component及其衍生
    作用域scope属性@Scope
    生命周期init-method/destroy@PostConstruct/@PreDestroy
    依赖注入<property>@Autowired/@Value
    第三方Bean管理<bean>@Bean
    配置文件加载<context:property-placeholder>@PropertySource
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值