Spring学习02----基于注解的IOC

1.Spring基于注解的IOC


1.1用于创建对象的注解

  • @Component:把当前类存入到spring容器中。其属性如下。
    • value:用于指定当前类的id,默认值是当前类名,且首字母改小写
  • @Controller:将当前表现层对象存入spring容器中。
  • @Service: 将当前业务层对象存入spring容器中。
  • @Repository: 将当前持久层对象存入spring容器中。

@Controller,@Service,@Repository注解的作用和属性与@Component是一模一样的,可以相互替代,它们的作用是使三层对象的分别更加清晰.

1.2用于注入数据的注解

  • 这些注解相当于bean.xml中的<property>标签。

  • @Autowired注解

    • 作用:
      • 自动按照类型注入
    • 注入的过程:
      • 1.当spring容器中有且只有一个对象的类型与要注入的类型相同时,注入该对象。
      • 2.当spring容器中有多个对象类型与要注入的类型相同时,使用要注入的变量名作为bean的id,在spring 容器查找,找到则注入该对象.找不到则报错 。
    • 出现位置:
      • 可以是成员变量上,也可以是方法上
    • 细节:
      • 使用注解注入时,set方法可以省略
  • @Qualifier注解:

    • 作用:
      • 在按照类中注入的基础上再按照名称注入。它在给类成员注入时不能单独使用,但是在给方法注入时可以。
    • 属性:
      • value:用于指定bean的id
  • @Resource注解:

    • 作用:
      • 直接按照bean的id注入。它可以独立使用 (可以看作上面两种注解的综合
    • 属性:
      • name:用于指定bean的id

以上三个注入都只能注入其他bean类型的数据,而基本类型和String类型无法通过上述注解实现

  • @Value:
    • 作用:
      • 注入基本数据类型和String类型数据
    • 属性:
      • 用于指定数据的值,它可以使用spring中的SpEL表达式(写法:${表达式}

1.3用于改变作用范围的注解

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

1.4 和生命周期相关的注解(了解)

  • @PreDestroy注解

    • 作用:
      • 用于指定销毁方法
  • PostConstruct注解

    • 作用
      • 用于指定初始化方法

1.5Spring中注解和XML的比较

  • 注解的优势:

    • 配置简单,维护方便(我们找到类,就相当于找到了对应的配置)。
  • XML的优势:

    • 修改时,不用改源码。不涉及重新编译和部署。
基于XML的配置基于注解的配置
Bean 定义<bean id = "..." class = "..." />@Component、@Controller、@Service、@Repository
Bean 名称通过 id 或者 name 属性指定@Component("person")
Bean 注入通过<property>或者<constructor-arg>标签注入@Autowired、@Qualifier、@Resource
Bean 作用范围通过scope属性指定@Scope
Bean 生命周期通过 init-method或者destroy-method属性指定初始化和销毁方法@PostConstruct、@PreDestroy
Bean 适合场景Bean 来自于第三方,无法修改源码Bean 的实现类由自己开发

2.使用spring的IOC实现账户的CRUD操作


2.1XML的方式

  • 整体目录结构图如下:
    在这里插入图片描述

  • 首先在pom.xml中导入相关依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>day02_eesy_02account_xmlioc</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.5.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.4</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.26</version>
        </dependency>

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

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.5.RELEASE</version>
        </dependency>
    </dependencies>
</project>
  • 创建数据库表并创建其对应的实体类:
create table account(
	id int primary key auto_increment,
	name varchar(40),
	balance doule
)character set utf8 collate utf8_general_ci;

insert into account(name,balance) values('aaa',1000);
insert into account(name,balance) values('bbb',1000);
insert into account(name,balance) values('ccc',1000);

/**
* 账户的实体类
*/
public class Account implements Serializable {
  private Integer id;
  private String name;
  private float money;

  public Integer getId() {
      return id;
  }

  public void setId(Integer id) {
      this.id = id;
  }

  public String getName() {
      return name;
  }

  public void setName(String name) {
      this.name = name;
  }

  public float getMoney() {
      return money;
  }

  public void setMoney(float money) {
      this.money = money;
  }

  @Override
  public String toString() {
      return "Account{" +
              "id=" + id +
              ", name='" + name + '\'' +
              ", money=" + money +
              '}';
  }
}
  • 编写持久层接口及其实现类:
/**
 * 持久层接口类
 */
public interface IAccountDao {
    /**
     * 查询所有
     * @return
     */
    List<Account> findAllAccount();

    /**
     * 查询一个
     * @return
     */
    Account findAccountById(Integer accountId);
    /**
     * 增
     */
    void saveAccount(Account account);

    /**
     * 删
     * @param accountId
     */
    void deleteAccount(Integer accountId);

    /**
     * 改
     * @param account
     */
    void updateAccount(Account account);
}

/**
 * 账户的持久层实现类
 */
public class AccountDaoImpl implements IAccountDao {

    private QueryRunner runner;

    public void setRunner(QueryRunner runner) {
        this.runner = runner;
    }

    public List<Account> findAllAccount() {
        try {
            return runner.query("select *from account",new BeanListHandler<Account>(Account.class));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Account findAccountById(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 void saveAccount(Account account) {
        try {
            runner.update("insert into account(name,money) values (?,?) ", account.getName(),account.getMoney());
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

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

    public void updateAccount(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 interface IAccountService {

    /**
     * 查询所有
     * @return
     */
    List<Account> findAllAccount();

    /**
     * 查询一个
     * @return
     */
    Account findAccountById(Integer accountId);
    /**
     * 增
     */
    void saveAccount(Account account);

    /**
     * 删
     * @param accountId
     */
    void deleteAccount(Integer accountId);

    /**
     * 改
     * @param account
     */
    void updateAccount(Account account);
}

/**
 * 账户的业务层实现类
 */
public class AccountServiceImpl implements IAccountService {

    private IAccountDao accountDao;

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

    public List<Account> findAllAccount() {
        return accountDao.findAllAccount();
    }

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

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

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

    public void updateAccount(Account account) {
        accountDao.updateAccount(account);
    }
}
  • 编写spring的配置文件bean.xml
<?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">

    <bean id="accountService" class="com.zut.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <bean id="accountDao" class="com.zut.dao.impl.AccountDaoImpl">
        <property name="runner" ref="queryRunner"></property>
    </bean>

    <!--配置QueryRunner-->
    <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
        <!--注入数据源-->
        <constructor-arg name="ds" ref="dataSource"></constructor-arg>
    </bean>

    <!--配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--连接数据库的必备信息-->
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/student"></property>
        <property name="user" value="root"></property>
        <property name="password" value="ljt074517"></property>
    </bean>
</beans>
  • 测试代码如下:
/**
 * 使用junit单元测试
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:bean.xml")
public class AccountServiceTest {

    @Autowired
    private IAccountService as;

    @Test
    public void testfindAll() {

        List<Account> accounts = as.findAllAccount();
        for (Account account:accounts){
            System.out.println(account);
        }

    }

    @Test
    public void testfindOne() {
        //1.获取容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //2.得到service
        IAccountService as = ac.getBean("accountService",IAccountService.class);

        Account account = as.findAccountById(1);
        System.out.println(account);
    }

    @Test
    public void testSave() {
        //1.获取容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //2.得到service
        IAccountService as = ac.getBean("accountService",IAccountService.class);

        Account account = new Account();
        account.setName("test");
        account.setMoney(123456);
        as.saveAccount(account);
    }

    @Test
    public void testUpdate() {
        //1.获取容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //2.得到service
        IAccountService as = ac.getBean("accountService",IAccountService.class);

        Account account = as.findAccountById(4);
        account.setMoney(1200);
        account.setName("test2");
        as.updateAccount(account);

    }

    @Test
    public void testDelete() {
        //1.获取容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //2.得到service
        IAccountService as = ac.getBean("accountService",IAccountService.class);

        as.deleteAccount(4);

    }
}

2.2注解+XML的方式

  • 配置文件bean.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
	
	<!-- 开启注解 -->
    <context:component-scan base-package="com.zut"></context:component-scan>

    <!--配置QueryRunner-->
    <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
        <!--注入数据源-->
        <constructor-arg name="ds" ref="dataSource"></constructor-arg>
    </bean>

    <!--配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--连接数据库的必备信息-->
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/student"></property>
        <property name="user" value="root"></property>
        <property name="password" value="ljt074517"></property>
    </bean>
</beans>

这里QueryRunnerComboPooledDataSource第三方类是存在于jar包中的,无法在它们的类上加上注解,所以还需要XML配置文件。

  • 持久层代码:
@Repository(value = "accountDao")
public class AccountDaoImpl implements IAccountDao {

    @Autowired
    private QueryRunner runner;

	//省略.............
  • 业务层代码:
@Service(value = "accountService")
public class AccountServiceImpl implements IAccountService {

    @Autowired
    private IAccountDao accountDao;

	//省略........

使用@Repository和@Service将标注的类存入到容器中去,@Autowired来进行依赖注入。代替了xml配置的<bean>标签

2.3纯注解配置

  • 如果要实现纯注解的配置,需要将上面bean.xml中的配置用注解来表示,这时我们引入一些新的注解:

  • @Configuration

    • 作用:指定当前类是一个配置类(用一个类来代替XML配置文件
    • 细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写 。
  • @ComponentScan

    • 作用:用于通过注解指定spring在创建时要扫描的包
    • 属性:
      • value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包我们使用此注解就等同于在xml中配置了<context:component-scan base-package=""></context:componentn>
  • @Bean

    • 作用:用于把当前方法的返回值作为bean对象并存入spring容器中
    • 属性:
      • name:用于指定bean的id。默认值为当前方法的名称
    • 细节:当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象,查找的方式和Autowired注解是一样的
  • @Import

    • 作用:用于导入其他的配置类
    • 属性:
      • value:用于指定其他注解的字节码,当使用import后,有Import注解的类就是父配置类
  • @PropertySource

    • 作用:用于指定properties文件的位置
    • 属性:
      • value:指定文件的名称和路径
  • 有了上面的这些注解后,我们可以把bean.xml改造为以下两个配置类。
//@Configuration
@ComponentScan("zut")
@Import(JDBCconfig.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {

}
/**
 * 和spring连接数据库相关的配置类
 */
//这里的Configuration注解就不能省略,虽然已经配置了对这个包进行了扫描,但是首先它要是一个配置类,才会对里面的注解进行扫描
//没有Configuration,spring扫描这个包也不会识别bean注解
@Configuration
public class JDBCconfig {

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

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

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

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

    @Bean(name = "queryRunner")
    @Scope("prototype")
    public QueryRunner createQueryRunner(DataSource dataSource){
        return new QueryRunner(dataSource);
    }

    @Bean(name = "dataSource")
    public DataSource createDataSource(){
        try {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driver);
            ds.setJdbcUrl(url);
            ds.setUser(username);
            ds.setPassword(password);
            return ds;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值