Spring(二):IOC注解开发

Source

Spring(二):IOC注解开发

1. spring基于XML的CRUD案例

1.1 环境搭建

  • 创建maven项目,导入坐标
<dependencies>
    <!--springIOC相关-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
	<!--spring整合Junit-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.1.3.RELEASE</version>
    </dependency>
	<!--mysql驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.26</version>
    </dependency>
    <!--druid连接池-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.0.9</version>
    </dependency>
	<!--jdbcTemplate相关-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.0.0.RELEASE</version>
    </dependency>
    <!--junit测试-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>RELEASE</version>
    </dependency>
</dependencies>
  • 数据库和实体类

public class Account {
    private Integer accountId;
    private Integer uid;
    private Double money;
}
  • dao层增删改查代码(接口为IAccountDao,这里省略不写)
package com.zmysna.dao.impl;

public class AccountDaoImpl implements IAccountDao {
	
    private JdbcTemplate jdbcTemplate;

    public void saveAccount(Account account) {
        jdbcTemplate.update("INSERT INTO account values(?,?,?)",
                account.getAccountId(), account.getUid(), account.getMoney());
    }

    public void updateAccount(Account account) {
        jdbcTemplate.update("UPDATE account SET uid=?, money=? where accountId=?",
                account.getUid(), account.getMoney(), account.getAccountId());
    }

    public Account findAccountById(int id) {
        try {
            return jdbcTemplate.queryForObject("select * from account where accountId = ?", new BeanPropertyRowMapper<>(Account.class), id);
        } catch (DataAccessException e) {
            e.printStackTrace();
            return null;
        }
    }

    public void deleteAccount(int id) {
        jdbcTemplate.update("DELETE FROM account where accountId = ?", id);
    }
}
  • service层增删该查代码(接口为IAccountService,这里省略不写)
public class AccountServiceImpl implements IAccountService{

    private IAccountDao accountDao;

    public Account getAccountById(int accountId) {
        Account accountById = accountDao.findAccountById(accountId);
        return accountById;
    }

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

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

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

1.2 spring容器配置,管理所有的java类

  • jdbc信息
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8
jdbc.username=root
jdbc.password=awsed2zx
jdbc.initialSize=3
jdbc.maxActive=50
  • applicationContext.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">
	<!--加载jdbc配置文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
   <!--配置数据库连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
	<!--配置jdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg ref="dataSource" name="dataSource"></constructor-arg>
    </bean>
	<!--配置dao层-->
    <bean id="accountDao" class="com.zmysna.dao.impl.AccountDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>
	<!--配置service层-->
    <bean id="accountService" class="com.zmysna.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

</beans>

1.3 测试

@Test
public void getAccountTest() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    IAccountService accountService = ac.getBean("accountService", IAccountService.class);
    System.out.println(accountService.getAccountById(1));
}

###2. spring常用注解介绍

2.1 创建对象加入容器

​ 使用@Component(“bean名称”)可以配置对象的名称

以下四个注解的功能都是相同的, 为了更好的标识不同的java类使用不同的注解

@Component 用于工具类、其他组件

@Component
public class Account {}

@Repository 标识数据库访问层的组件

@Repository("accountDao") //创建dao层对象加入容器
public class AccountDaoImpl implements IAccountDao {}

@Service 标识业务逻辑层的组件

@Service("accountService") //创建service层对象加入容器
public class AccountServiceImpl implements IAccountService{}

@Controller 标识控制层的组件

2.2 依赖注入

  • @Autowired

    • 从容器中找对象,给属性赋值。根据类型、名称去容器中找。
    1. 注入到属性上面
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    1. 注入到方法形参中(方法名可以随意定义)
    @Autowired
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    
  • @Qualifier

    • 结合 Autowired 使用,可以指定按照名称去容器找对象注入。
    @Autowired
    @Qualifier("jdbcTemplate") //根据"jdbcTemplate"这个名称到容器中寻找对象
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    
  • @Value

    • 给简单类型属性直接赋值/获取配置文件值@Value(“${key}”)
    1. 简单类型属性
    @Value("11")  //给简单类型属性赋值
    private int i;
    
    1. 获取配置文件值

      1. 配置文件
      jdbc.username=root
      
      1. 赋值
      @Value("${jdbc.username}")
      private String username;
      
  • @Resource

    从容器中找对象,给属性赋值。 根据名称、类型去容器中查找。和 Autowired 功能类似,查找对象的顺序是想查找名称,再查找类型,和Autowired相反。只能在 jdk1.5~1.8 使用, 不推荐使用。

####2.3 作用范围

@Scope:和bean标签中的scope属性功能相同

设置bean的作用范围,取值如下:
singleton:单例,默认值
prototype:多例
request:web项目中,将对象存入request域中
session: web项目中,将对象存入session域中
globalsession:web项目中,应用在集群环境中, 如果没有集群环境,相当域session

使用

@Component
// 指定对象是单例还是多例,默认是单例
//@Scope("singleton") // 默认值
@Scope("prototype") // 多例
public class Account {}

2.4 生命周期和懒加载

@PostConstruct:用于指定初始化方法,相当于:<bean id="" class="" init-method=""/>

@PreDestroy:用于指定销毁方法:相当于<bean id="" class="" init-method="" destroy-method=""/>

@Lazy:懒加载,只能用于单例对象。

@Component
@Lazy //开启懒加载
public class Account {
    public Account(){
        System.out.println("1. 创建对象");
    }
    // 表示再创建对象之后执行
    @PostConstruct
    public void init_(){
        System.out.println("2. 执行 init 初始化方法");
    }
    // 表示在销毁容器时候执行
    @PreDestroy
    public void destroy_(){
        System.out.println("3. 执行 destroy 释放资源的方法,在关闭容器时候执行。");
    }
}

2.5 配置文件信息注解

​ 将配置文件中的信息也用注解表示,实现纯注解无配置开发。

@Configuration

​ 用于指定当前类是一个 spring 配置类, 当创建容器时会从该类上加载注解。 获取容器时需要使用AnnotationApplicationContext(有@Configuration 注解的类.class)。

@ComponentScan

​ 用于指定 spring 在初始化容器时要扫描的包。 作用和在 spring 的 xml 配置文件中的:<context:component-scan base-package=“com.itheima”/>是一样的。

@PropertySource

​ 用于加载.properties 文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到 properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。

@Bean
该注解只能写在方法上,表明使用此方法创建一个对象,并且放入spring 容器

@Import

​ 用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration 注解。当然,写上也没问题。

3 改造CRUD案例,实现纯注解开发

3.1 配置文件信息注解化

  • xml配置文件类
package config;

//指定当前类为Spring配置类
@Configuration
//指定初始容器时扫描的包
@ComponentScan("com.zmysna")
//导入其他配置文件类
@Import(JdbcConfig.class)
public class SpringConfiguration {
}
  • JDBC注解配置

    1. 配置文件 jdbc.properties
    jdbc.driverClassName=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8
    jdbc.username=root
    jdbc.password=awsed2zx
    jdbc.initialSize=3
    jdbc.maxActive=50
    
    1. 配置类
    package config;
    
    import com.alibaba.druid.pool.DruidDataSource;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.PropertySource;
    import org.springframework.jdbc.core.JdbcTemplate;
    
    import javax.sql.DataSource;
    
    //加载配置文件
    @PropertySource(value = "classpath:jdbc.properties")
    public class JdbcConfig {
        //@${}读取配置文件信息
        @Value("${jdbc.driverClassName}")
        private String driverClassName;
        @Value("${jdbc.url}")
        private String url;
        @Value("${jdbc.username}")
        private String username;
        @Value("${jdbc.password}")
        private String password;
    
        //使用方法得到的DataSource对象放到容器中,指定名称为dataSource
        @Bean("dataSource")
        public DataSource createDataSource(){
            DruidDataSource druidDataSource = new DruidDataSource();
            druidDataSource.setUsername(username);
            druidDataSource.setPassword(password);
            druidDataSource.setUrl(url);
            druidDataSource.setDriverClassName(driverClassName);
            return druidDataSource;
        }
    
         //使用方法得到的DataSource对象放到容器中,指定名称为jdbcTemplate
        @Bean("jdbcTemplate")
        public JdbcTemplate createJdbcTemplate(@Qualifier("dataSource") DataSource dataSource){
            return new JdbcTemplate(dataSource);
        }
    }
    

3.2 dao层

package com.zmysna.dao.impl;

//创建对象加入到容器中,对象名称是accountDao
@Repository("accountDao") 
public class AccountDaoImpl implements IAccountDao {
    
    //按照类型和名称自动注入jdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
	...各种方法省略
}

3.3 service层

//创建对象加入到容器中,对象名称是accountService
@Service("accountService")
public class AccountServiceImpl implements IAccountService{

    private IAccountDao accountDao;
    
	//按照类型和名称自动注入accountDao(给accountDao赋值)
    @Autowired
    public void setAccountDao(IAccountDao accountDao) {
        this.accountDao = accountDao;
    }
}

3.4 测试

public class AnnoTest {

    @Test
    public void springAnnoTest() {
        //通过AnnotationConfigApplicationContext加载注解配置类,创建容器。
        ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
        IAccountService accountService = ac.getBean("accountService", IAccountService.class);
        System.out.println(accountService.getAccountById(1));
    }
}