基于注解的DI(依赖注入):
对于 DI 使用注解,将不再需要在 Spring 配置文件中声明 Bean 实例。只需要在 Spring 配置文件中配置组件扫描器,用于在指定的基本包中扫描注解。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" 5 http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://www.springframework.org/schema/context 8 http://www.springframework.org/schema/context/spring-context.xsd"> 9 <!-- 只扫描子包,不扫描当前包 --> 10 <!-- <context:component-scan base-package="com.tongji.*"/> --> 11 <!-- 先扫描子包,再扫描当前包 --> 12 <!-- <context:component-scan base-package="com.tongji"/> --> 13 14 <context:component-scan base-package="com.tongji.di01"/> 15 </beans>
注意:添加的约束http://www.springframework.org/schema/context/spring-context.xsd
注解基本注入:
1 package com.tongji.di01; 2 3 import org.springframework.beans.factory.annotation.Value; 4 import org.springframework.context.annotation.Scope; 5 import org.springframework.stereotype.Component; 6 7 //与本注解具有相同功能的注解还有三个: 8 //@Repository:注解在Dao接口的实现类上,表示当前Dao类为组件 9 //@Service:注解在Service接口的实现类上,表示当前Service类为组件 10 //@Controller:注解在Controller接口的实现类上,表示当前Controller类为组件(SpringMVC) 11 @Component("student") //表明当前类为组件,容器创建的这个组件对象名称为myStudent,相当于<bean/>的id属性 12 @Scope("prototype") //设置Bean的作用范围,默认是singleton 13 public class Student { 14 @Value("张三") //为name属性赋值 15 private String name; 16 private int age; 17 18 public String getName() { 19 return name; 20 } 21 22 public void setName(String name) { 23 System.out.println("执行setName"); 24 this.name = name; 25 } 26 27 public int getAge() { 28 return age; 29 } 30 31 @Value("23") //可以将该注解放到set上 32 public void setAge(int age) { 33 this.age = age; 34 } 35 36 @Override 37 public String toString() { 38 return "Student [name=" + name + ", age=" + age + "]"; 39 } 40 41 }
解释:注解注入时,POJO类可以没有setXXX()方法,但还是写上去比较好。
注解域属性的自动注入:
(1) 用Spring自带的注解实现:
1 @Component("myStudent") 2 @Scope("prototype") 3 public class Student { 4 @Value("张三") 5 private String name; 6 @Value("23") 7 private int age; 8 @Autowired //byType方式自动注入 9 private School school;
1 @Component("myStudent") 2 @Scope("prototype") 3 public class Student { 4 @Value("张三") 5 private String name; 6 @Value("23") 7 private int age; 8 @Autowired 9 @Qualifier("mySchool") //byName方式自动注入 10 private School school;
补充:@Autowired 还有一个属性 required,默认值为 true,表示当匹配失败后,会终止程序运行。若将其值设置为 false,则匹配失败,将被忽略,未匹配的属性值为 null。
(2)使用JDK提供的注解实现:
1 @Component("myStudent") 2 @Scope("prototype") 3 public class Student { 4 @Value("张三") 5 private String name; 6 @Value("23") 7 private int age; 8 @Resource //byType方式自动注入 9 private School school;
1 @Component("myStudent") 2 @Scope("prototype") 3 public class Student { 4 @Value("张三") 5 private String name; 6 @Value("23") 7 private int age; 8 @Resource(name="mySchool") //byName方式自动注入 9 private School school;
注解Bean的定制声明始末:
1 @PostConstruct 2 public void postInit() { 3 System.out.println("初始化完毕之后"); 4 } 5 6 @PreDestroy 7 public void preDestory() { 8 System.out.println("销毁之前"); 9 }
在方法上使用@PostConstruct,与原来的 init-method 等效。在方法上使用@PreDestroy,与 destroy-method 等效。
使用JavaConfig进行配置:
JavaConfig,是在 Spring 3.0 开始从一个独立的项目并入到 Spring 中的。JavaConfig 可以看成一个用于完成 Bean 装配的配置文件,只不过是程序员使用 Java 自己编写的。
1 package com.tongji.di07; 2 3 import org.springframework.beans.factory.annotation.Autowire; 4 import org.springframework.context.annotation.Bean; 5 import org.springframework.context.annotation.Configuration; 6 7 @Configuration //表明当前POJO类将会被当作配置文件来使用,即Spring容器 8 public class MyJavaConfig { 9 10 @Bean(name="mySchool") //表明当前方法的返回值为一个Bean对象 11 public School mySchoolCreater() { 12 return new School("清华大学"); 13 } 14 15 @Bean(name="school") //byName方式需要定义的该Bean的name值与被注入的属性名相同 16 public School mySchoolCreater2() { 17 return new School("北京大学"); 18 } 19 20 //@Bean(name="myStudent", autowire=Autowire.BY_TYPE) //byType方式自动注入 21 @Bean(name="myStudent", autowire=Autowire.BY_NAME) //byName方式自动注入 22 public Student myStudentCreater() { 23 return new Student("赵六",26); 24 } 25 }
解释:此时School类和Student类就不需要注解了。
使用 junit4 测试 Spring:
对 Spring 程序的运行,首先需要创建容器对象,而后还要从容器中获取对象,再对其进行执行。但,JUnit4 对 Spring 程序有专门的测试方法。
1 package com.tongji.di08; 2 3 import org.junit.Test; 4 import org.junit.runner.RunWith; 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.beans.factory.annotation.Qualifier; 7 import org.springframework.test.context.ContextConfiguration; 8 import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; 9 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 10 11 //使用Spring的测试 12 @RunWith(SpringJUnit4ClassRunner.class) 13 @ContextConfiguration(locations="classpath:com/tongji/di08/applicationContext.xml") 14 public class MyTest2 extends AbstractJUnit4SpringContextTests { 15 16 @Autowired //byType 17 @Qualifier("myStudent") //byName 18 private Student student; 19 @Test 20 public void test01() { 21 System.out.println(student); 22 } 23 24 }
注意:Student对象的注入方式可以是基于XML的,也可以是基于注解的。
注解与XML共同使用:
注解的好处是,配置方便,直观。但其弊端也显而易见:以硬编码的方式写入到了 Java代码中,其修改是需要重新编译代码的。
XML 配置方式的最大好处是,对其所做修改,无需编译代码,只需重启服务器即可将新的配置加载。
若注解与 XML 同用,XML 的优先级要高于注解。这样做的好处是,需要对某个 Bean做修改,只需修改配置文件即可。当然,此时,Bean 类要有 setXXX() 或构造器。