Spring 学习笔记 Part04
1. 基于注解的 IoC 配置
注解配置和 xml 配置要实现的功能都是一样的,都是要降低程序间的耦合。只是配置的形式不一样。
<!-- beans.xml配置 -->
基于注解整合时,导入约束时需要多导入一个 context 名称空间下的约束。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
告知 spring 创建容器时要扫描的包
<context:component-scan base-package="com.itheima"/>
</beans>
2. 注解基本标签介绍
2.1 用于创建对象的
他们的作用就和在XML配置文件中编写一个 标签实现的功能是一样的。
@Component //用于把当前类对象存入spring容器中
属性:
value:用于指定bean的id。当我们不写时,它的默认值是当前类名,且首字母改小写。
@Controller //一般用在表现层
@Service //一般用在业务层
@Repository //一般用在持久层
属性:
value:用于指定bean的id。当我们不写时,它的默认值是当前类名,且首字母改小写。
以上三个注解他们的作用和属性与Component是一模一样。
他们三个是spring框架为我们提供明确的三层使用的注解,使我们的三层对象更加清晰(作为@Component的语义化别名仅此而已)。
2.2 用于注入数据的
他们的作用就和在XML配置文件中编写一个 标签或者标签实现的功能是一样的。
<!-- bean类型的注解注入 -->
@Autowired //自动按照类型注入 (一开始不匹配beanid,而是直接匹配类型,类型匹配不成功则用变量名称去匹配beanid)
出现位置:
可以是变量上,也可以是方法上。
只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功。如果ioc容器中没有任何bean的类型和要注入的变量类型匹配,则报错。
在使用注解注入时,set方法就不是必须的了。
@Qualifier //在按照类中注入的基础之上再按照名称注入 (使用注解的value值直接匹配beanid)
如果Ioc容器中有多个类型匹配时使用
出现位置:
在给类成员注入时不能单独使用,必须配合@Autowired。
在给方法参数注入时可以单独使用。
属性:
value:用于指定注入bean的id。
@Resource //直接按照bean的id注入
其效果等于@Autowired配合@Qualifier。
它可以独立使用。
属性:
name:用于指定bean的id。
以上三个注入都只能注入其他bean类型的数据,而基本类型和String类型无法使用上述注解实现
<!-- 基本数据类型和String类型的注解注入 -->
@Value //用于注入基本类型和String类型的数据
属性:
value:用于指定数据的值。它可以使用spring中SpEL(也就是spring的el表达式)
SpEL的写法:${表达式}
<!-- 集合类型的注解注入 -->
集合类型的注入只能通过XML来实现
2.3 用于改变作用范围的
他们的作用就和在bean标签 中使用scope属性实现的功能是一样的。
@Scope //用于指定bean的作用范围
只能作用在类上。
属性:
value:指定范围的取值。常用取值:singleton、prototype、request、session、globalsession
2.4 和生命周期相关的
他们的作用就和在bean标签中使用init-method和destroy-method的作用是一样的。
@PostConstruct //用于指定初始化方法
@PreDestroy //用于指定销毁方法
3. 注解新标签介绍
创建一个配置类,它的作用和bean.xml是一样的。
@Configuration //指定当前类是一个配置类
当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
@ComponentScans //包含@ComponentScan数组
@ComponentScan //用于通过注解指定spring在创建容器时要扫描的包
我们使用此注解就等同于在xml中配置了:<context:component-scan base-package="com.itheima"/>
属性:
value、basePackages:它们作用是一样的,都是用于指定创建容器时要扫描的包。
@Bean //用于把当前方法的返回值作为bean对象存入spring的容器中IoC容器中
当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。(查找的方式和Autowired注解查找的方式是一样的)
属性:
name:用于指定bean的id。当不写时,默认值是当前方法的名称
@Import //用于导入其他的配置类
当我们使用Import的注解之后,有Import注解的类就父配置类,而导入的都是子配置类。
属性:
value:用于指定其他配置类的字节码。
@PropertySource //用于指定properties文件的位置
属性:
value:指定文件的名称和路径。
关键字:classpath,表示类路径下
上节补充:
@Qualifier //贴在方法参数上时可单独出现,类成员时则需配合Autowire
属性:
value:指定要注入参数的beanid
创建基于注解配置的IoC容器的实现类:
AnnotationApplicationContext ( )
构造方法参数: 有 @Configuration 注解的类.class(用于指定配置类的字节码)
实例
//配置文件主类
@Configuration
@ComponentScan("com.itheima")
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {
}
//和spring连接数据库相关的jdbc配置子类
@Configuration
@ComponentScan("com.itheima")
@Import(otherConfig.class)
@PropertySource("classpath:jdbcConfig.properties")
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对象 */
@Bean(name="runner")
@Scope("prototype")
public QueryRunner createQueryRunner(@Qualifier("ds2") DataSource dataSource){
return new QueryRunner(dataSource);
}
/* 创建数据源对象 */
@Bean(name="ds2")
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);
}
}
@Bean(name="ds1")
public DataSource createDataSource1(){
try {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass(driver);
ds.setJdbcUrl("jdbc:mysql://localhost:3306/eesy02");
ds.setUser(username);
ds.setPassword(password);
return ds;
}catch (Exception e){
throw new RuntimeException(e);
}
}
}
补充个内容,当xml引入外部config.properties时,使用的标签是< context:property-placeholder >
<context:property-placeholder location="classpath:jdbcConfig.properties"/>
<bean id="ds" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
4. Spring 注解整合 Junit
每个测试方法都有两行取IoC容器的代码:
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
AccountService as = ac.getBean("accountService",AccountService.class);
如果不写的话,直接会提示空指针异常。junit不能为我们创建spring容器,因为它不知晓我们是否使用了spring框架,但junit给我们暴露了一个注解,让我们可以替换掉它的运行器。
Spring 整合 junit 步骤:
第 1 步:导入 spring 整合 junit 的 jar 坐标 —— spring-test 。
第 2 步:使用 junit 提供的一个注解 @Runwtih 把原有的main方法替换掉,替换成spring提供的。
第 3 步:用注解 @ContextConfiguration 告知 spring 的运行器,spring 和 IoC 创建时基于xml还是注解的,并且说明位置。
属性:
locations:指定xml文件的位置,加上classpath关键字,表示在类路径下。
classes:指定注解类所在的位置,返回值为 .class 字节码类型
第 4 步:使用 @Autowired 给测试类中的变量注入数据
//spring × junit 实例
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:bean.xml"})
public class AccountServiceTest {
@Autowired
private IAccountService as ;
@Test
methods...
}
注意:当我们使用 spring 5.x 版本时,要求 junit 的 jar必须是4.12及以上。
5. Spring 注解和 XML 的选择问题
注解的优势:
配置简单,维护方便(我们找到类,就相当于找到了对应的配置)。
XML的优势:
修改时,不用改源码。不涉及重新编译和部署。
两种方式的比较:
总结:
企业没有要求的情况下,XML和注解混用是最合适的。
自己写的类用注解配置更方便;
jar包中的类用XML配置更方便。
拓展:为什么不把测试类配置到xml中呢?
首先一个问题,配到 XML 中能不能用呢?
答案是肯定的,没问题,可以使用,但是没必要。
其次,为什么不采用xml配置方式呢?
第一:当我们在 xml 中配置了一个 bean,spring 加载配置文件创建容器时,就会创建对象。
第二:测试类只是我们在测试功能时使用,而在项目中它并不参与程序逻辑,也不会解决需求上的问题,所以创建完了,并没有使用。那么存在容器中就会造成资源的浪费。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/84501.html