spring基于注解的IOC以及IoC的案例
spring中ioc的常用注解
1.用于创建对象的注解
相当于:<bean id = "" class="">
这些注解的作用相当于bean.xml中的标签,把资源让spring来管理。
@Component
: 把当前类对象存入spring容器中,其属性如下:
value: 用于指定当前类的id. 不写时默认值是当前类名,且首字母改小写
@Controller
: 一般用于表现层的注解
@Service
: 一般用于业务层层的注解
@Repository
: 一般用于持久层的注解
@Controller,@Service,@Repository
注解的作用和属性与@Component
是一模一样的,可以相互替代,它们的作用是使三层对象的分别更加清晰。
2.用于注入数据的注解
相当于:
-
<property name = "" ref="">
-
<property name = "" value="">
@Autowired
: 自动按照成员变量类型注入,只能注入其他bean类型。
注入过程
当spring容器中有且只有一个对象的类型与要注入的类型相同时,注入该对象.当spring容器中有多个对象类型与要注入的类型相同时,则使用要注入的变量名作为bean的id在spring 容器查找,找到则注入该对象.找不到则报错.
出现位置: 既可以在变量上,也可以在方法上
细节: 使用注解注入时,set方法可以省略@Qualifier
: 在自动按照类型注入的基础之上,再按照bean的id注入.
出现位置: 既可以在变量上,也可以在方法上.注入变量时不能独立使用,必须和@Autowire
一起使用; 注入方法时可以独立使用.@Resource
: 直接按照bean的id注入,使用时相当于同时使用@Autowired
和@Qualifier
两个注解.
@Value
: 注入基本数据类型和String类型数据
用于改变作用范围的注解
相当于:<bean id = "" class= "" scope = "">
@Scope
: 指定bean的作用范围
属性:
value: 用于指定作用范围的取值,“singleton”,“prototype”,“request”,“session”,“globalsession”
和生命周期相关的注解(了解)
这些注解的作用相当于bean.xml中的标签的init-method和destroy-method属性:
@PostConstruct
: 用于指定初始化方法
@PreDestroy
: 用于指定销毁方法
spring的半注解配置和纯注解配置
半注解配置
在半注解配置下,spring容器仍然使用ClassPathXmlApplicationContext类从xml文件中读取IOC配置,同时在xml文件中告知spring创建容器时要扫描的包.
例如,使用半注解模式时,上述简单实例中的beans.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">
<!--告知spring在创建容器时要扫描的包,配置此项所需标签不在beans的约束中,而在一个名为context的名称空间和约束中-->
<context:component-scan base-package="com.itheima"></context:component-scan>
</beans>
然后将spring注解加在类的定义中.
纯注解配置
在纯注解配置下,我们用配置类替代bean.xml,spring容器使用AnnotationApplicationContext类从spring配置类中读取IOC配置
如果我们把下面这句关键配置转换为注解形式那就很好了:
<!-- 告知spring在创建容器时要扫描的包 -->
<context:component-scan base-package="com.itheima"></context:component-scan>
要用到下面两个注解:
1.@Configuration
: 用于指定当前类是一个spring配置类,当创建容器时会从该类上加载注解.获取容器时需要使用
AnnotationApplicationContext(有@Configuration注解的类.class)
2.@ComponentScan
: 指定spring在初始化容器时要扫描的包,作用和bean.xml 文件中<context:component-scan base-package=“要扫描的包名”/>是一样的. 其属性如下:
basePackages: 用于指定要扫描的包,是value属性的别名
等价于xml配置的示例代码:
@Configuration
@ComponentScan("com.itheima")
public class SpringConfiguration {
}
我们已经配置好要扫描的包,但是下面这段数据源和QueryRunner如果配置呢?
<!--配置QueryRunner-->
<bean id="runner" 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/eesy"></property>
<property name="user" value="root"></property>
<property name="password" value="1234"></property>
</bean>
@Bean
: 该注解只能写在方法上,表明使用此方法创建一个对象,并放入spring容器,其属性如下:
name: 指定此方法创建出的bean对象的id
细节: 使用注解配置方法时,如果方法有参数,Spring框架会到容器中查找有没有可用的bean对象,查找的方式与@Autowired
注解时一样的.
@PropertySource
: 用于加载properties配置文件中的配置.例如配置数据源时,可以把连接数据库的信息写到properties配置文件中,就可以使用此注解指定properties配置文件的位置,其属性如下:
value: 用于指定properties文件位置.如果是在类路径下,需要写上"classpath:"
和spring连接数据库相关的配置类
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
* 用于创建一个QueryRunner对象
* @param dataSource
* @return
*/
@Bean(name="runner")
public QueryRunner createQueryRunner(DataSource dataSource){
return new QueryRunner(dataSource);
}
/**
* 创建数据源对象
* @return
*/
@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);
}
}
}
增加一串代码
@PropertySource("classpath:jdbcConfig.properties")
jdbcConfig.properties文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/eesy
jdbc.username=root
jdbc.password=1234
@Import
: 用于导入其他配置类.当我们使用@Import注解之后,有@Import注解的类就是父配置类,而导入的都是子配置类. 其属性如下:
value: 用于指定其他配置类的字节码
Spirng整合junit
问题
在测试类中都有以下两行代码:
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
IAccountService as = ac.getBean("accountService",IAccountService.class);
作用是获取容器如果不写会出现空指针异常。
解决:
1、导入spring整合junit的jar(坐标)
2、使用Junit提供的一个注解把原有的main方法替换了,替换成spring提供的@RunWith
3、告知spring的运行器,spring和ioc创建是基于xml还是注解的,并且说明位置 @ContextConfiguration
属性:
locations:指定xml文件的位置,加上classpath关键字,表示在类路径下
classes:指定注解类所在地位置
注意:当我们使用spring 5.x版本的时候,要求junit的jar必须是4.12及以上
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class AccountServiceTest {
//再使用@Autowired给测试类变量注入数据
@Autowired
private IAccountService as = null;