Java -- Spring学习笔记4、基于注解的DI
1、基于注解的DI
对于DI使用注解,将不再需要在Spring配置文件中声明bean实例。Spring中使用注解,需要在Spring配置文件中配置组件扫描器,用于在指定的基本包中扫描注解。
1.1、指定多个包的三种方式
- 使用多个context:component-scan指定不同的包路径:
<context:component-scan base-package="com.rg.entity"/>
<context:component-scan base-package="com.rg.service"/>
- 指定base-package的值使用分隔符
分隔符可以使用逗号分号还可以使用空格,不建议使用空格。
<context:component-scan base-package="com.rg.entity,com.rg.service"/>
- base-package 是指定到父包名
base-package的值表是基本包,容器启动会扫描包及其子包中的注解,当然也会扫描到子包下级的子包。所以 base-package 可以指定一个父包就可以。
<context:component-scan base-package="com.rg"/>
- 或者最顶级的父包
<context:component-scan base-package="com"/>
但不建议使用顶级的父包,扫描的路径比较多,导致容器启动时间变慢。指定到目标包和合适的。也就是注解所在包全路径。例如注解的类在com.rg.entity包中:
<context:component-scan base-package="com.rg.entity"/>
2、定义Bean的注解@Component
需要在类上使用注解@Component,该注解的value属性用于指定该bean的id值。
@Component 不指定 value 属性,bean 的 id 是类名的首字母小写。
- 首先在配置文件配置组件扫描器
<context:component-scan base-package="com.rg.entity"/>
- 实体类如下:
@Component("myClient")
public class Client
{
private int id;
private String name;
//setter toString()....
}
- 测试方法:
@Test
public void test04()
{
String config = "applicationContext.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
Client client = (Client) ctx.getBean("myClient");
client.setId(1);
client.setName("大力");
System.out.println(client);
}
2.1、简单类型属性注入@Value
需要在属性上使用注解@Value,该注解的value属性用于指定要注入的值。使用该注解完成属性注入时,类中无需setter。
- 实体类中使用Value注解:
@Component("myClient")
public class Client
{
@Value("1001")
private int id;
@Value("贝贝")
private String name;
//setter toString....
}
- 测试方法:
@Test
public void test04()
{
String config = "applicationContext.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
Client client = (Client) ctx.getBean("myClient");
System.out.println(client);
}
2.2、byType自动注入@Autowired
需要在引用属性上使用注解@Autowired,该注解默认使用按类型自动装配Bean的方式。使用该注解完成属性注入时,
- 实体类如下:
@Component("myClient")
public class Client
{
@Value("1001")
private int id;
@Value("贝贝")
private String name;
@Autowired
private School school;
//setter toString....
}
@Component
public class School
{
@Value("宾夕法尼亚大学")
private String name;
//toString.......
}
- 测试方法同上。
2.3、byName自动注入@Autowired与@Qualifier
需要在引用属性上联合使用注解@Autowired与@Qualifier。@Qualifier的value属性用于指定要匹配的Bean的id值。
- 实体类如下:
//Client类如下:
@Component("myClient")
public class Client
{
@Value("1001")
private int id;
@Value("贝贝")
private String name;
@Autowired
@Qualifier(value = "mySchool")
private School school;
}
//School类如下:
@Component("mySchool")
public class School
{
@Value("宾夕法尼亚大学")
private String name;
}
- 测试方法同上。
- @Autowired还有一个属性required,默认值为true,意思是当匹配失败后,程序运行会终止、抛出异常、表示没找到。若将其值设置为false,匹配失败将被忽略,未匹配的属性值为null。
3、JDK注解@Resource自动注入
Spring提供了对jdk中@Resource注解的支持。@Resource注解既可以按名称匹配,也可以按类型匹配。默认是按名称注入。使用该注解,要求JDK必须是6及以上版本。@Resource可在属性和set方法上。
3.1、byType注入引用类型属性
@Resource注解若不带任何参数,采用默认按名称的方式注入,按名称不能注入Bean,则会按照类型进行Bean的匹配注入。
- 实体类如下:
@Component("myClient")
public class Client
{
@Value("1001")
private int id;
@Value("贝贝")
private String name;
//名称:school
//类型:School
@Resource
private School school;
//setter toString....
}
//名称:mySchool
//类型:School
@Component("mySchool")
public class School
{
@Value("宾夕法尼亚大学")
private String name;
//setter toString()....
}
3.2、byName注入引用类型属性
@Resource注解指定其name属性,则name的值即为按照名称进行匹配的Bean的id。
- 实体类如下:
@Component("myClient")
public class Client
{
@Value("1001")
private int id;
@Value("贝贝")
private String name;
//指明名称为:mySchool
@Resource(name = "mySchool")
private School school;
//setter toString....
}
//名称:mySchool
@Component("mySchool")
public class School
{
@Value("宾夕法尼亚大学")
private String name;
//setter toString()....
}
- 测试方法同上。
概括来讲、注解更方便、直观、代码少,没有配置文件的书写那么复杂、但是、以硬编码的方式写入到 Java 代码中,修改是需要重新编译代码的。XML方式配置和代码是分离的、在 xml 中做修改,无需编译代码,只需重启服务器即可将新的配置加载、缺点是:编写麻烦,效率低,大型项目过于复杂