Spring--二、Spring基于注解的IOC及IOC的案例

Spring–二、Spring基于注解的IOC及IOC案例

视频:Spring5教程IDEA版-4天-2018黑马

教学资源 提取码:cwbz

基于注解的IOC配置和xml配置实现的功能都是一样的,都是降低程序间的耦合,只是配置的形式不一样。

Spring中IOC的常用注解

注解分类

  1. 用于创建对象的:作用和在xml配置文件中写一个bean标签实现的功能相同
  2. 用于注入数据的:作用和在xml配置中的bean标签中写一个property标签功能相同
  3. 用于改变作用范围的:作用和bean标签使用scope属性实现功能相同
  4. 和生命周期相关:作用和在bean标签中使用init-methoddestory-method作用相同

环境搭建

导入jar包

在基于注解的配置中,我们还要将aop的jar包拷贝到lib目录

使用@Component注解配置管理的资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//账户的业务层实现类  
@Component("accountService")
public class AccountServiceImpl implements IAccountService {
private IAccountDao accountDao;
public void setAccountDao(IAccountDao accountDao) {
this.accountDao = accountDao;
}
}

//账户的持久层实现类
@Component("accountDao")
public class AccountDaoImpl implements IAccountDao {
private DBAssit dbAssit;
}

注意:当我们使用注解注入时,set方法不用写。

创建Spring的xml配置文件并开启对注解的支持

导入约束时需要多导入一个context名称空间下的约束,并且告知Spring在创建容器时要扫描的包。

常用注解

相当于:

1
<bean id="" class="">

用于创建对象的

@Component
  • 作用:把资源让Spring来管理,相当于在xml中配置一个bean。
  • 属性:
    • value:指定bean的id。如果不指定value属性,默认bean的id是当前类的类名,首字母小写。
@Controller @Service @Repository

这三个注解和Component注解的衍生,作用及属性都是一模一样的,只不过提供了更加明确的语义化:

  • @Controller:一般用于表现层的注解
  • @Service:一般用于业务层的注解
  • @Repository:一般用于持久层的注解

细节:如果注解中有且只有一个属性要赋值时,且名称是value,value在赋值时可以不写。

用于注入数据的

相当于:

1
2
<property name="" ref=""></property>
<property name="" value=""></property>
@Autowired

在Spring的IOC容器中寻找变量自动按类型匹配。(容器中的变量即用@Component或其他三个注解的对象)当使用注解注入属性时,set方法可以忽略。它只能注入其他bean类型。

作用:

  • 当只有一个变量的类型匹配时则成功。
  • 当有多个变量的类型匹配时,使用要注解的对象变量名称作为bean的id,在Spring的IOC容器中查找,找到了就可以注入成功,找不到就报错。

出现位置:

​ 可以是变量上,也可以是方法上。

@Qualifier

作用:在自动按照类型注入的基础之上,再按照Bean的id注入。它在给字段注入时不能独立使用,必须和@Autowired一起使用;但是给方法参数注入时,可以独立使用。

属性:value:指定bean的id。

@Resource

作用:直接按照Bean的id注入。它也只能注入其他bean类型。

属性:name:指定bean的id

@Value

作用:注入基本数据类型和String类型数据的

属性: value:用于指定值(可以支持Spring的SpEL表达式:${表达式})

用于改变作用范围的

相当于

1
<bean id="" class="" scope="">
@Scope

作用: 指定bean的作用范围。

属性: value:指定范围的值。 取值:singleton prototype request session globalsession

和生命周期相关(了解)

相当于

1
<bean id="" class="" init-method="" destroy-method="" />
@PostConstruct

作用: 用于指定初始化方法。

@PreDestroy

作用: 用于指定销毁方法。

关于Spring注解和XML的选择问题

  • 注解的优势: 配置简单,维护方便(我们找到类,就相当于找到了对应的配置)。
  • XML的优势: 修改时,不用改源码。不涉及重新编译和部署。

两者比较:1570196055969

案例使用xml方式和注解方式实现单表的CRUD操作

CRUD即增(Create)、查(Retrieve)、改(Update)、删(Delete)

此处可看链接视频的P35-P38

改造基于注解的IOC案例,使用纯注解的方式实现

经过上面的改造,我们还有几种配置需要从xml改成注解配置。

@Configuration

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

属性: value:用于指定配置类的字节码

@ComponentScan

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

属性: basePackages:用于指定要扫描的包。和该注解中的value属性作用一样。

例:

1
2
3
@Configuration 
@ComponentScan("com.itheima")
public class SpringConfiguration { }

@Bean

作用: 该注解只能写在方法上,表明使用此方法创建一个对象,将方法的返回值放入spring容器。

属性: name:给当前@Bean注解方法创建的对象指定一个名称(即bean的id)(当不写时默认为当前方法的名字)。

细节:当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象,查找方式和Autowired注解的作用是一样的。

例:

1
2
3
4
@Bean(name="dbAssit") 
public DBAssit createDBAssit(DataSource dataSource) {
return new DBAssit(dataSource);
}

@Import

作用: 用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration注解。当然,写上也没问题。 有import的为父配置类,导入的是子配置类。

属性: value[]:用于指定其他配置类的字节码。

1
2
3
4
@Configuration 
@ComponentScan(basePackages = "com.itheima.spring")
@Import({ JdbcConfig.class})
public class SpringConfiguration { }

@PropertySource

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

属性: value[]:用于指定properties文件位置。如果是在类路径下,需要写上classpath:

1
2
3
4
5
6
7
8
9
jdbc.properties文件: 
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/day44_ee247_spring
jdbc.username=root
jdbc.password=1234

@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig{ }

Spring和Junit的整合

JUnit是一个Java编程语言的单元测试框架。

问题及解决思路

在测试类中,每个测试方法都有以下两行代码:

1
2
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
IAccountService as = ac.getBean("accountService",IAccountService.class);

这两行代码的作用分别是获取容器和创建业务层对象,如果不写的话,直接会提示空指针异常。所以又不能轻易删掉。但是测试人员不会管你使用的到底是什么框架,所以可能他根本不知道容器是个什么东西,所以我们需要的是程序能自动帮我们创建容器

Junit的一个注解可以让我们替换他的运行器,这时我们可以用这个注解将运行器替换为spring框架的运行器,它可以读取配置文件(或注解)来创建容器。我们只需要告诉它配置文件在哪就行了。

配置

导入jar包

导入spring-test的jar包和spring-aop的jar包。

使用@RunWith注解替换原有运行器

例:

1
2
@RunWith(SpringJUnit4ClassRunner.class) 
public class AccountServiceTest { }

使用@ContextConfiguration指定spring配置文件的位置

例:

1
2
3
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations= {"classpath:bean.xml"})
public class AccountServiceTest { }

@ContextConfiguration注解:

  • locations属性:用于指定配置文件的位置。如果是类路径下,需要用classpath:表明
  • classes属性:用于指定注解的类。当不使用xml配置时,需要用此属性指定注解类的位置。

使用@Autowired给测试类中的变量注入数据

例:

1
2
3
4
5
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations= {"classpath:bean.xml"})
public class AccountServiceTest {
@Autowired private IAccountService as ;
}

为什么不把测试类配到xml中

  1. 当我们在xml中配置了一个bean,spring加载配置文件创建容器时,就会创建对象。
  2. 测试类只是我们在测试功能时使用,而在项目中它并不参与程序逻辑,也不会解决需求上的问题,所以创建完了,并没有使用。那么存在容器中就会造成资源的浪费。

接下来请看下一篇。。。

Donate comment here