Spring(基于注解的IOC配置)
一、利用 spring的 IoC(xml配置)来实现账户的 CRUD[掌握]
步骤一:创建工程并导入依赖(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.0http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.itcast.spring</groupId>
<artifactId>spring_day02</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--springIOC相关-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<!--springjdbc相关-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
步骤二:创建数据库和实体类
创建数据库:
create table account(
id int primary key auto_increment,
name varchar(40),
money float
)character set utf8 collate utf8_general_ci;
insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);
自己编写实体类Account(私有,有getter和setter方法、重写tostring)
步骤三:创建service接口和实现类
接口:
实现类:
步骤四:创建dao接口和实现类
接口:
实现类:
步骤五:创建配置文件
步骤六:创建测试用例
步骤七:加载外部资源文件
在类的根路径下添加jdbc.properties:
内容如下:
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/heima25
jdbc.username=root
jdbc.password=root
修改applicationContext.xml:
二、 基于注解的IOC配置[掌握]
1、 明确:写在最前
注解配置和xml配置要实现的功能都是一样的,都是要降低程序间的耦合。
2、环境搭建
2.1 创建maven工程并导入坐标
复制spring_day02然后重命名为spring_day02_02即可:重命名工程、重命名pom.xml中的artifactId,删除其他文件只留下src和pom.xml,然后在idea中打开即可。
2.2 使用注解装配bean
@Component
作用: 在类上使用该注解,把资源让spring来管理。相当于在xml中配置一个bean。( <bean id="" class="">)
属性: value:指定bean的id。如果不指定value属性,默认bean的id是当前类的类名。首字母小写。
@Controller @Service @Repository
他们三个注解都是针对@Component的衍生注解,他们的作用及属性都是一模一样的。
他们只不过是提供了更加明确的语义化。
@Controller:一般用于表现层(web)的注解。
@Service:一般用于业务层(service)的注解。
@Repository:一般用于持久层(dao)的注解。
细节:如果注解中有且只有一个属性要赋值时,且名称是value,value在赋值时可以不写。
步骤一:创建配置文件
先配置注解扫描的包,如图:红色
步骤二:使用注解装配bean
装配service:
/**
* @Component注解:相当于配置了<bean>标签
* value = "accountService":相当于配置了bean标签的id属性,单独配置value时,可以省略value属性名称。
*/
装配dao:
步骤三:进行测试
创建demo的测试方法分别获取service的实现类和dao的实现类,发现@Component的注解已经生效。
但是如果使用其他的crud的测试方法,会报空指针异常。
原因:AccountDaoImpl并没有被注入到AccountServiceImpl中。(相当于xml文件中红色部分没有配置)
<bean id="accountService" class="cn.itcast.service.impl.AccountServiceImpl"> //@Component
<property name="accountDao" ref="accountDao"></property> //@Autowired
</bean>
2.3 用于注入数据的
@Autowired
作用:
自动按照类型注入。当使用注解注入属性时,set方法可以省略。它只能注入其他bean类型。当有多个类型匹配时,使用要注入的对象的变量名称作为bean的id,在spring容器查找,找到了也可以注入成功。找不到就报错。
service实现类
dao实现类:
@Qualifier
作用: (1)在自动按照类型注入的基础之上,再按照Bean的id注入。它在给字段注入时不能独立使用,必须和@Autowire一起使用;(2)但是给方法参数注入时,可以独立使用。
属性: value:指定bean的id。
添加第二个dao实现类:
内容如下:复制AccountDaoImpl后重命名为AccountDaoImpl2即可
指定注入AccountDaoImpl2:
@Resource
作用: 直接按照Bean的id注入。它也只能注入其他bean类型。(相当于@Autowired+@Qualifier)
属性: name:指定bean的id。
@Value
作用: 注入基本数据类型和String类型数据的
属性: value:用于指定值
注解装配bean和注解注入的使用方式(重点)
1、自己编写的类,都可以使用注解装配到容器中。
2、没有办法使用注解装配的第三方的类,可以使用<bean>标签装配。
3、只要是在spring容器中的bean,都可以使用注解注入。
2.4 用于改变作用范围的
相当于:<bean id="" class="" scope="">
@Scope
作用:指定bean的作用范围。
属性:value:指定范围的值。取值:singleton prototype request session globalsession
2.5 和生命周期相关的:(了解)
相当于:<bean id="" class="" init-method="" destroy-method="" />
@PostConstruct
作用:用于指定初始化方法。
@PreDestroy作用:
作用:用于指定销毁方法。
2.6 关于Spring注解和XML的选择问题
注解的优势:
配置简单,维护方便(我们找到类,就相当于找到了对应的配置)。
XML的优势:
修改时,不用改源码。
Spring管理Bean方式的比较:
三、案例:使用注解IOC改造作业[掌握]
步骤一:创建maven工程并导入坐标
复制spring_day02_02然后重命名为spring_day02_03即可:重命名工程、重命名pom.xml中的artifactId,删除其他文件,只留下src和pom.xml后,通过idea打开即可。
步骤二:创建web层
创建一个AccountController,假设属于web层,只需测试新增方法即可。
步骤三:创建service接口和实现类
实现类:修改注入方式即可。
接口:和之前的一样
实现类:
步骤四:创建dao接口和实现类
实现类:修改注入方式即可。
接口:和之前的一样
实现类:
步骤六:创建配置文件
步骤七:创建测试用例
创建web层的测试用例:
2、待改造的问题
我们发现,之所以我们现在离不开xml配置文件,是因为我们有一句很关键的配置:
<!-- 告知spring框架在,读取配置文件,创建容器时,扫描注解,依据注解创建对象,并存入容器中 -->
<context:component-scan base-package="cn.itcast"></context:component-scan>
如果他要也能用注解配置,那么我们就离脱离xml文件又进了一步。
另外,数据源和QueryRunner的配置也需要靠注解来实现。
3、新注解说明
@Configuration
作用:
用于指定当前类是一个spring配置类,当创建容器时会从该类上加载注解。(相当于applicationContext.xml文件)
获取容器时需要使用AnnotationApplicationContext(有@Configuration注解的类.class)。
示例代码:
/**
* spring的配置类,相当于applicationContext.xml文件
*/
@Configuration
public class SpringConfiguration {
}
注意:
我们已经把配置文件用类来代替了,但是如何配置创建容器时要扫描的包呢?
请看下一个注解
@ComponentScan
作用:
用于指定spring在初始化容器时要扫描的包。作用和在spring的xml配置文件中的:
<context:component-scan base-package="cn.itcast"></context:component-scan>
属性:
Value(单独使用可省略):用于指定要扫描的包。和标签中的base-Package属性作用一样。
示例代码:
@Configuration //spring的配置类,相当于applicationContext.xml文件
@ComponentScan("cn.itcast") //配置扫描的包
public class SpringConfiguration {
}
注意:
我们已经配置好了要扫描的包,但是数据源和QueryRuner对象如何从配置文件中移除呢?
请看下一个注解。
@Bean
作用: 该注解只能写在方法上,将方法的返回值作为一个bean,并且放入spring容器。
属性: name:给当前@Bean注解方法创建的对象指定一个名称(即bean的id)。
注意:
我们已经把数据源和QueryRunner从配置文件中移除了,此时可以删除bean.xml了。
但是由于没有了配置文件,创建数据源的配置又都写死在类中了。如何把它们配置出来呢?
请看下一个注解。
@PropertySource
作用:
用于加载.properties文件中的配置(加载外部资源文件)。例如我们配置数据源时,可以把连接数据库的信息写到properties配置文件中,就可以使用此注解指定properties配置文件的位置。
属性:
value[]:用于指定properties文件位置。如果是在类路径下,需要写上classpath:
@Import
作用:
用于导入其他配置类,在引入其他配置类时,其他类上可以不用再写@Configuration注解。当然,写上也没问题。
属性:
value[]:用于指定其他配置类的字节码。
示例代码:
@Configuration //声明这是一个配置类
@ComponentScan("cn.itcast") //配置扫描包
@Import(value = { JdbcConfig.class }) //导入JdbcConfig配置类(首字母大写)
public class SpringConfiguration {
}
@Configuration//写不写都行
@PropertySource(value = { "classpath:jdbc.properties" }) //加载外部资源
public class JdbcConfig {
}
注意:
我们已经把要配置的都配置好了,但是新的问题产生了,由于没有配置文件了,如何获取容器呢?
请看下一小节。
通过注解获取容器
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
4、纯注解案例
步骤一:环境搭建
复制之前的工程,重命名工程名称,重命名pom.xml中的artifactId, 删除其他文件,只留下src和pom.xml后,通过idea打开即可。
步骤二:创建配置类
如果在一个配置类中需要装配很多的bean到容器中,那么显然将所有的bean放在一个配置类是非常不利于管理的,因此我们可以选择将bean分拆到其他类中单独管理,最后再通过配置类来引入其他类即可。
在resources类的根目录下创建properties资源文件:
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/heima25
jdbc.username=root
jdbc.password=root
springConfiguration:
步骤三:测试
四、 Spring整合junit
1、 测试类中的问题和解决思路
问题:
在测试类中,每个测试方法都有以下两行代码:
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountController accountController = (AccountController) ac.getBean("accountController");
这两行代码的作用是获取容器,如果不写的话,直接会提示空指针异常。所以又不能轻易删掉。
解决思路分析
针对上述问题,我们需要的是程序能自动帮我们创建容器。一旦程序能自动为我们创建spring容器,我们就无须手动创建了,问题也就解决了。
我们都使用过junit,但是junit都无法知晓我们是否使用了spring框架,更不用说帮我们创建spring容器了。不过好在,junit给我们暴露了一个注解,可以让我们替换掉它的运行器。
这时,我们需要依靠spring框架,因为它提供了一个运行器,可以读取配置文件(或注解)来创建容器。我们只需要告诉它配置文件在哪就行了。
2、 涉及的注解
@RunWith
作用: 替换掉junit的运行器,换成一个可以初始化spring容器的运行器。
属性: value:单独配置时,value属性名称可以省略,配置SpringJUnit4ClassRunner.class来代替原来junit的运行器
@ContextConfiguration
作用: 加载配置类或者xml配置文件
属性:
value[]:用来指定xml配置文件的路径 location
class[]: 用来指定配置类 classes
3、 Xml的配置步骤
步骤一:环境搭建
复制之前的spring_day02_03(含xml配置文件)工程重命名后修改pom.xml中的artifactId,然后删除其他文件,只留下src和pom.xml后,通过idea打开即可。
步骤二:导入spring-test的坐标
此处需要注意的是,spring5及以上版本要求junit的版本必须是4.12及以上,否则用不了。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
步骤三:测试
4、 纯注解的配置步骤(配置类)
步骤一:环境搭建
复制spring_day02_04(含配置类)重命名后修改pom.xml中的artifactId,然后删除其他文件,只留下src和pom.xml后,通过idea打开即可。
步骤二:导入spring-test的坐标
此处需要注意的是,spring5及以上版本要求junit的版本必须是4.12及以上,否则用不了。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
步骤三:测试
-
注解总结
-
用于装配Bean的注解
-
@Component(value=”xxx”):
一般用于将三层以为的bean装配到容器中,value可以省略,value的属性值作为bean的id
@Component的三个衍生注解:
@Controller(value=”xxx”):
一般用于将web层装配到容器中,使用方法和@Component(value=”xxx”)一摸一样
@Service(value=”xxx”):
一般用于将web层装配到容器中,使用方法和@Component(value=”xxx”)一摸一样
@Repository(value=”xxx”):
一般用于将web层装配到容器中,使用方法和@Component(value=”xxx”)一摸一样
-
用于属性注入的注解
@Autowired:
只能按照bean类型注入,如果有多个类型匹配,默认将属性名称作为id去容器中查找。
@Qualifier:
一般和@Autowired配合使用,用来注入指定id的bean,做方法的参数中可以独立使用
@Resource:
用来注入指定id的bean类型,相当于@Autowired+@Qualifier
@Value:
只能注入基本类型等数据,不能注入bean类型,可以使用${}在资源文件中获取数据,前提是,外部资源文件被加载。
-
作用域的
@Scope:
用于指定bean的作用域,一般就是singleton和prototype
-
生命周期相关的
@PostConstruct:
用于指定某一个方法为初始化方法
@PreDestroy:
用于指定某一个方法为销毁方法
-
其他配置类相关的
@Configuration:
声明一个类为配置类,用于替代applicationContext.xml的
@ComponentScan:
用于开启注解扫描的包
@Import:
用于导入其他类的
@PropertySource:
用于加载外部资源文件的
@Bean:
用于将方法返回的bean类型的对象装配到容器中
-
Junit相关的
@RunWith:
用于替换底层的运行器,初始化spring容器的
@ContextConfiguration
用于指定配置文件或者配置类的