03.基于注解 Spring--IOC

明确

  • 学习基于注解的 IoC 配置,大家脑海里首先得有一个认知,即注解配置和 xml 配置要实现的功能都是一样 的,都是要降低程序间的耦合,只是配置的形式不一样
  • 关于实际的开发中到底使用xml还是注解,每家公司有着不同的使用习惯。所以这两种配置方式我们都需要掌握(我觉得想xml+注解是比较好的)
  • 注解的优势:
      配置简单,维护方便(我们找到类,就相当于找到了对应的配置)
  • XML的优势:
      修改时,不用改源码,不涉及重新编译和部署

常用注解

用于创建对象:相当于:< bean id="" class="" > 标签

  • @Controller 、@Service 、@Repository 、都是@Component的衍生注解,它们的作用及属性都是一模一样的
注解作用属性
@Component相当于在 xml 中配置一个 beanvalue:指定 bean 的 id。如果不指定 value 属性,默认 bean 的 id 是当前类的类名,首字母小写
@Controller一般用于表现层的注解和@Component一样
@Service一般用于业务层的注解和@Component一样
@Repositor一般用于持久层的注解和@Component一样

用于注入数据:相当于:< property name="" ref="" > 或< property name="" value="" >标签

注解作用属性
@Autowired自动按照类型注入,当使用注解注入属性时,set方法可以省略。它只能注入其他 bean 类型。当有多个 类型匹配时,使用要注入的对象变量名称作为 bean 的 id,在 Spring 容器查找,找到了也可以注入成功。找不到就报错required:默认为true,该bean必须存在,否则就会注入失败
@Qualifier在自动按照类型注入的基础之上,再按照 Bean 的 id 注入,它在给字段注入时不能独立使用,必须和 @Autowire 一起使用;但是给方法参数注入时,可以独立使用value:指定 bean 的 id
@Resource直接按照 Bean 的 id 注入,它也只能注入其他 bean 类型name:指定 bean 的 id
@Value注入基本数据类型和 String 类型数据的value:用于指定值

用于改变作用范围:相当于:< bean id="" class="" scope="" >

注解作用属性
@Scope指定 bean 的作用范围value:指定范围的值,取值:singleton、prototype、request session、globalsession

和生命周期相关:(了解)相当于:< bean id="" class="" init-method="" destroy-method="" / >

注解作用
@PostConstruct用于指定初始化方法
@PreDestroy用于指定销毁方法

和纯注解开发相关

注解作用属性
@Configuration用于指定当前类是一个 spring 配置类,当创建容器时会从该类上加载注解。获取容器时需要使用 AnnotationApplicationContext(有@Configuration 注解的类.class)value:用于指定配置类的字节码
@ComponentScan用于指定 spring 在初始化容器时要扫描的包,作用和在 spring 的 xml 配置文件中的: < context:component-scan base-package=“com.zsc” />是一样的basePackages:用于指定要扫描的包。和该注解中的 value 属性作用一样
@Bean该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器和name:给当前@Bean 注解方法创建的对象指定一个名称(即 bean 的 id)
@PropertySource用于加载.properties 文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到 properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置value[]:用于指定 properties 文件位置。如果是在类路径下,需要写上 classpath:
@Value用于获取.properties文件中的值,与@PropertySource对应value:用于指定.properties文件里面的key值
@Import用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration 注解。当然,写上也没问题value[]:用于指定其他配置类的字节码

通过注解获取容器

// SpringConfiguration.class是配置类的字节码文件
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class); 

基于纯注解的CRUD操作案例

  • 依赖坐标
	<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <!--Spring的测试依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>
        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
  • 实体类
@Data
public class Account implements Serializable {
    private Integer id;
    private String name;
    private Float money;
}
  • dao层实现类(接口省略)
@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {
    @Autowired
    private QueryRunner runner;

    public void save(Account account) {
        try {
            runner.update("insert into account(name,money)values(?,?)", account.getName(), account.getMoney());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    public void update(Account account) {
        try {
            runner.update("update account set name=?,money=? where id=?", account.getName(), account.getMoney(), account.getId());
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    public void delete(Integer accountId) {
        try {
            runner.update("delete from account where id=?",accountId);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    public Account findById(Integer accountId) {
        try {
            return runner.query("select * from account where id=?",new BeanHandler<Account>(Account.class),accountId);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    public List<Account> findAll() {
        try {
            return runner.query("select * from account ",new BeanListHandler<Account>(Account.class));
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}
  • service层实现类(接口省略)
// 默认使用首字母小写的类名作id,也可以自己指定
// 自己指定名称被注入的话,先匹配类型,如果只有一个就直接注入,多个则匹配名称
@Service("accountService")
public class AccountServiceImpl implements IAccountService {
    // 使用@Autowired注解时,set方法可以省略
    // 若要指定别名则用@Qualifier,给字段注入时必须与@Autowired一起使用
    @Autowired
    private IAccountDao accountDao;

    public void setAccountDao(IAccountDao accountDao) {
        this.accountDao = accountDao;
    }

    public void save(Account account) {
        accountDao.save(account);
    }

    public void update(Account account) {
        accountDao.update(account);
    }

    public void delete(Integer accountId) {
        accountDao.delete(accountId);
    }

    public Account findById(Integer accountId) {
        return accountDao.findById(accountId);
    }

    public List<Account> findAll() {
        return accountDao.findAll();
    }
}
  • .properties配置文件
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springlearn?serverTimezone=UTC
jdbc.username=root
jdbc.password=123
  • JDBC文件配置类
public class JdbcConfiguration {
    @Value("${jdbc.driver}")
    private String driver;

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;
    /**
     * Bean注解:
     *      属性:
     *          name:用于指定bean的id,当不写时,默认是当前方法的名称
     *      细节:Bean注解在配置方法时,如果方法有参数,spring框架回去容器中查找有没有可用的bean对象,
     *              查找的方式和Autowired注解的作用是一样的
     *
     * @return
     */
    @Bean("dataSource")
    public DataSource createDataSource(){
        try{
            // 新建连接池
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setUser(username);
            ds.setPassword(password);
            ds.setJdbcUrl(url);
            ds.setDriverClass(driver);
            return ds;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
    // Bean注解在配置方法时,如果方法有参数,spring框架回去容器中查找有没有可用的bean对象,查找的方式和Autowired注解的作用是一样的
    @Bean(name="runner")
    // 开启多例模式
    @Scope("prototype")
    public QueryRunner createQueryRunner(DataSource dataSource){
        return new QueryRunner(dataSource);
    }
}
  • 主配置文件
/**
 * Configuration注解:
 *     作用:指定当前类是一个配置类
 *     细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
 *
 * PropertySource注解:
 *      作用:
 *          指定properties文件位置
 *      属性:
 *          value:指定文件的路径
 *                  关键字:classpath,表示在类路径下
 *
 * ComponentScan注解:
 *      作用:用于通过注解指定spring在创建容器时扫描的包,我的理解:接收扫描用注解形式创建的bean对象
        属性:
 *          value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
 *                 我们使用此注解就等同于在xml中配置了:
 *                      <context:component-scan base-package="com.itheima"></context:component-scan>
 *
 * Import注解
 *      作用:用于导入其他配置类
 *      细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
 *      属性:
 *          value:指定文件的名称路径
 *                  关键字:classpath,表示在类路径下
 */
// 可写可不写,因为测试类中已经指定了该类的字节码文件
//@Configuration
@ComponentScan("com.zsc")
@Import(JdbcConfiguration.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {

}
/**
 * 使用Junit单元测试:测试我们的配置
 * 因为junit不知道我们使用了什么框架,所以不会帮我自动创建bean容器,因此我们要导入spring整合junit的jar包
 * @RunWith 把启动器换成spring整合junit
 * 告知spring的运行器,spring和IOC创建是基于xml还是注解的,并说明配置文件的位置
 * @ContextConfiguration 注解:
 *          属性:
 *              location:指定xml的位置,要加上关键字classpath,指定在类路径下
 *              classes:指定以注解形式配置的配置文件的位置
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class test {
    @Autowired
    private IAccountService accountService;
    @Test
    public void test(){
        System.out.println("测试查询全部操作");
        List<Account> lists = accountService.findAll();
        lists.forEach(System.out::println);
        System.out.println("测试按id查找操作");
        Account account = accountService.findById(1);
        System.out.println(account);
        System.out.println("测试保存操作");
        Account account1 = new Account();
        account1.setMoney(2000f);
        account1.setName("test");
        accountService.save(account1);
        System.out.println("测试删除操作");
        accountService.delete(1);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值