Spring 学习2
看了一些 Spring 的教程后,发现很多东西的配置大概都有2种方式,注解配置和 XML 配置。他们都能实现一样的功能,只是形式不一样。
注解的好处:配置简单。
XML 的好处:修改时不用改源码。
在实际开发中用哪一种方式,看习惯,因为2种方式都有可能会用到,所以2种方式都应该学一下。这一篇主要记录使用注解配置的方式。
常用注解
在基于注解的配置中要把 Spring 的 一个 aop 的 jar 包放进项目里。
创建对象
@Component
作用:把资源给 Spring 管理。相当于在 XML 中配置一个 bean。
属性:
- value:指定 bean 的 id。如不指定,则默认 bean 的 id 是当前类的类名并且首字母小写。
@Component("accountService")
public class AccountServiceImpl implements IAccountService {
private IAccountDao accountDao;
public void setAccountDao(IAccountDao accountDao) {
this.accountDao = accountDao;
}
}
这里就是指定了这个 bean 的 id 为 accountService。
提示:使用注解注入时,set 方法不用写。如果注解中有且只有一个属性要赋值时,且名称是 value,value 在赋值是可以不写。
bean.xml
使用注解整合时,要多导入一个 context 名称空间的约束。
<?xml version="1.0" encoding="UTF-8"?>
<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.rgb3"></context:component-scan>
</beans>
@Controller @Service @Repository
@Component 为 @Service、@Controller、@Repository 的元注解,四个注解实现的功能是一样的。只不过后面3个是提供了更加明确的语义化,都可以用来创建对象。
- @Controller:一般用于控制层
- @Service:一般用于服务层
- @Repository:一般用于持久层
@Component 、 @Service、@Controller、@Repository 相当于 XML 配置里的:
<bean id="apple" class="xxx"></bean>
注入数据
@Autowired
自动按照类型注入。当使用注解注入属性时,set 方法可以省略,它只能注入其他 bean 类型。可以写在变量上或方法上。
当有多个类型匹配时,使用要注入的对象变量名称作为 bean 的 id,在 spring 的 IoC 容器查找,找到了也可以注入成功。找不到就报错。
这里在 IoC 容器中找到2个 IAccountDao 实现类(绿色圈),所以需要在这2个里面,找跟变量名一样的那个实现类(红色圈),完成自动注入。
@Qualifier
在 @Autowired 的基础之上,再按照 bean 的 id 注入。它在给变量注入时不能独立使用,必须和 @Autowired 一起使用;但是给方法参数注入时,可以独立使用。
属性: value:指定 bean 的 id。
@Autowired
@Qualifier("accountDao2")
private IAccountDao accountDao;
这样在 IoC 容器中找到2个 IAccountDao 实现类然后会找id为 accountDao2 的 bean,完成自动注入。
@Resource
直接按照 Bean 的 id 注入。它也只能注入其他 bean 类型。 属性 name:指定 bean 的 id。
@Resource(name="accountDao2")
private IAccountDao accountDao;
这样在 IoC 容器中直接找 id 为 accountDao2 的 bean,完成注入。
@Value
注入基本数据类型和 String 类型数据。属性 value:用于指定值 。支持 Spring 的 EL表达式 :
@Value("${jdbc.driver}")
private String driver;
注入数据的注解相当于
<bean id="accountService" class="com.rgb3.service.impl.AccountServiceImpl">
<property name="name" value="mike"></property>
<property name="age" value="21"></property>
<property name="birthday" ref="now"></property>
</bean>
<bean id="now" class="java.util.Date"></bean>
集合类型的数据只能通过 XML 方式配置。
改变 bean 的作用域范围
@Scope
指定 bean 的作用域范围,属性 value:指定范围(singleton prototype request session globalsession )。
相当于 XML 中:
<bean id="apple" class="xxx" scope="">
生命周期相关
@PostConstruct
指定初始化方法
@PreDestroy
指定销毁方法
配置类
@Configuration
之前在 XML 文件里配置 bean 的信息大部分用上面的注解实现了,现在 XML 里还有这行
<context:component-scan base-package="com.rgb3"></context:component-scan>
@Configuration 注解用来指定一个类作为 Spring 配置类。当创建容器时会从该类上加载注解,获取容器时需要使用 AnnotationApplicationContext(配置类.class)
属性:value:用于指定配置类的字节码
@Configuration
public class MySpringConfiguration {... }
@ComponentScan
指定 Spring 在初始化容器时要扫描的包,就和上面 XML 文件里剩下的扫描包的语句作用一样。
@Configuration
@ComponentScan("com.rgb3")
public class MySpringConfiguration {... }
@Bean
只能写在方法上,表示这个方法创建一个对象并存入 Spring 容器中。
属性:name: 给这个方法创建的对象指定一个 id
@Bean(name="myTool2")
public MyTool createMyTool(){
MyTool myTool=new MyTool();
//...
return myTool;
}
@PropertySource
用于加载 .properties 文件中的配置。如我们配置数据源时,可以把连接数据库的信息写到 .properties 配置文件中,就可以用此注解指定 .properties 配置文件的位置
属性: value[ ]: 用于指定 properties 文件位置。如果是在类路径下,需要写上 classpath:
写在 XML 文件里的数据源配置在java里也可以配置
public class JdbcConfig {
@Bean(name="dataSource")
public DataSource createDataSource() {
try {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setUser("root");
ds.setPassword("123");
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql:///my_spring_db");
return ds;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//...
}
可以改为这样
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;
@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);
}
}
}
再创建一个 jdbc.properties 文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/my_spring_db
jdbc.username=root
jdbc.password=123
@Import
用于导入其他配置类,在引入其他配置类时,可以不写@Configuration 注解。
现在有2个配置类 JdbcConfig 和 MySpringConfiguration ,现在把他们联系起来
@Configuration
@ComponentScan(basePackages="com.rgb3")
@Import({JdbcConfig.class})
public class MySpringConfiguration{...}
@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig{...}
通过注解获取容器
之前在 java 里通过 XML 配置文件获取容器
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
可以改为
ApplicationContext ac = new AnnotationConfigApplicationContext(MySpringConfiguration.class);
提示:配置类和配置文件可以写在类路径下任意位置。
Spring 整合 Junit
在测试时每次都要写代码去读取配置文件(或注解配置类)获取容器再进行相关操作,这里 Spring 框架提供了一个运行器,可以读取配置文件(或注解)来创建容器,不用自己手动创建。
导入 spring-test-5.0.2.RELEASE.jar 这个 jar 包
@RunWith 替换原有运行器
@ContextConfiguration 指定 Spring 配置文件的位置
@ContextConfiguration 注解的属性 :
locations :用于指定配置文件的位置。如果是类路径下,需要加 classpath:
classes :用于指定注解配置的类。当不使用 XML 配置时,要用此属性指定注解配置类的位置。
@RunWitch(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:bean.xml"})
public class MySpringTest{...}
onfiguration 指定 Spring 配置文件的位置
@ContextConfiguration 注解的属性 :
locations :用于指定配置文件的位置。如果是类路径下,需要加 classpath:
classes :用于指定注解配置的类。当不使用 XML 配置时,要用此属性指定注解配置类的位置。
@RunWitch(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:bean.xml"})
public class MySpringTest{...}
提示:不应该把测试配置到 XML 文件中,Spring 加载配置文件创建容器时,就会创建对象,这些对象里有一些只是测试用的,实际不用,这时创建测试用对象会浪费资源。