配置注解扫描
对于DI使用注解,将不再需要在Spring配置文件中声明部bean实例。Spring中使用注解,需要在原有Spring运行环境基础上在做一些改变,完成以下三个步骤:
(1)导入AOP的JAR包。因为注解的后台实现用到了AOP编程。
- spring-aop-4.2.1.RELEASE.jar
(2)需要更换配置文件头,即添加相应的约束:【context约束】 - 约束在%spring_home%docsspring-framework-referencehtmlxsd-configuration.html文件中。
(3)需要在Spring配置文件中配置组件扫描器,用于在指定的基本包中扫描注解。
<context:component-scan base-package="com.zhy.service" />
1. 常见注解
1. @Component:定义Bean,需要在类上使用@Component,该注解的value属性用于指定该Bean的id值。
// 该注解参数省略了value属性,该属性用于指定Bena的id
@Component("myStudent")
public class Student{
private String name;
private int age;
}
另外:Spring还提供了3个功能基本和@Component等效的注解:
@Reposity:用于对DAO实现类进行注解【WEB层】
@Service:用于对Service实现类进行注解【业务层】
@Controller:用于对Controller实现类进行注解【持久层】
之所以创建这三个功能与@Component等效的注解,是为了以后对其进行功能上的扩展,是他们不再等效。
2. @Scope:Bean的作用域,需要在类上使用注解@Scope,其value属性用于指定作用域,默认为singleton。
@Scope(scopeName="prototype")
@Component("UserService")
public class UserServiceImpl implements IUserService{
public void doSome(){
System.out.println("执行doSome()……");
}
}
- @Value:基本类型属性输入。需要在属性上使用注解@Value,该注解的value属性用于指定要注入的值。使用该注解完成属性注入时,类中可无需setter。当然,若属性有setter,则也可将其加到setter上。
设置在属性上:通过反射的Field赋值,破坏了封装性。
设置在setter上:通过setter方法赋值,推荐使用。
@Component("myStudent")
public class Student{
@Value("张三")
private String name;
@Value(23);
private int age;
@Override
public String toString(){
return "Student [ name="+name+",age"+age+"]";
}
}
3. @Autowired:自动装配,按类型byType注入域属性
需要在域属性上使用注解@Autowired,该注解默认使用按类型自动装配Bean的方式。使用该注解完成属性注入时,类中无需setter。当然,若属性有setter,则也可将其加到setter上。
@Autowired还有一个属性required,默认值为true。表示当匹配失败后,会终止程序运行,若将其值设置为false,则匹配失败后,将被忽略,未匹配的属性值为null。
问题:如果匹配多个类型一致的对象,将无法选择具体注入哪一个对象,从而引出了@Qualifier注解。
@Component("mySchool")
public class School{
@Value("清华大学")
private String name;
}
@Component("myStudent")
public class Student{
@Value("张三")
private String name;
@Value(23)
private int age;
@Autowired
private School school;
}
4. @Qualifier:按名称注入域属性【前提:联合@Autowired一起使用】
需要在域属性上联合使用注解@Autowired与@Qualifier。@Qualifier的value属性用于指定要匹配的Bean的id值。同样类中无需setter,也可加到setter上。
@Autowired还有一个属性required,默认值为true。表示当匹配失败后,会终止程序运行,若将其值设置为false,则匹配失败后,将被忽略,未匹配的属性值为null。
@Component("mySchool")
public class School{
@Value("清华大学")
private String name;
}
@Component("myStudent")
public class Student{
@Value("张三")
private String name;
@Value(23)
private int age;
@Autowired(required=false)
@Qualifier("mySchool")
private School school;
}
5. @Resource:自动装配【可按名称装配,也可按类型装配】
Spring提供了对JSR-250规范中定义@Resource标准注解的支持。@Resource注解即可以按名称匹配Bean,也可以按类型匹配Bean。使用该注解,要求JDK必须是6及以上版本。
@Resource相当于@Autowired和@Qualifier一起使用。
(1)按类型注入域属性
@Resource注解若不带任何参数,则会按照类型进行Bean的匹配注入。
@Component("mySchool")
public class School{
@Value("清华大学")
private String name;
}
@Component("myStudent")
public class Student{
@Value("张三")
private String name;
@Value(23)
private int age;
@Resource
private School school;
}
(2)按名称注入域属性
@Resource注解指定其name属性,则name的值即为按照名称进行匹配的Bean的id。
@Component("mySchool")
public class School{
@Value("清华大学")
private String name;
}
@Component("myStudent")
public class Student{
@Value("张三")
private String name;
@Value(23)
private int age;
@Resource(name="mySchool")
private School school;
}
6. @PostConstruct与@PreDestroy:Bean的声明始末
在方法上使用@PostConstruct,与原来的init-method等效。在方法上使用@PreDestroy,与destroy-method等效。
@PostConstruct
public void setUp(){
System.out.println("Bean初始化后,执行……");
}
@PreDestroy
public void tearDown(){
System.out.println("Bean销毁前,执行……");
}
7. 使用JavaConfing进行配置(了解)
JavaConfig是在Spring3.0开始从一个独立的项目并入到Spring中的。JavaConfig可以堪称一个用于完成Bean装配的Spring配置文件,即Spring容器,只不过该容器不是XML文件,而是由程序员使用Java自己编写的Java类。
(1)定义实体类
public class School{
private String name;
// setter
// toString()
}
public class Student{
private String name;
private int age;
private School school;
// setter
// toString()
}
(2)@Configuration/@Bean:定义JavaConfig类
对于一个POJO类,在类上使用@Configuration注解,将会使当前类作为一个Spring的容器来使用,用于完成bean的创建。
在该JavaConfig的方法上使用@Bean,将会使一个普通方法所返回的结果变为指定名称的Bean实例。
当然,在JavaConfig中,也可以完成域属性的自动注入。
A: byType方式的域属性自动注入
// 该注解表示:本类为JavaConfig
@Configuration
public class MyJavaConfig{
// 该注解表示:方法返回的对象Bean的名称(id)为mySchool
@Bean(name="mySchool")
public School initialSchool(){
return new School("清华大学");
}
// 采用byType自动注入school属性。当然,要求当前JavaConfig
// 类中只能与一个方法返回值与Student的School属性具有is-a关系
@Bean(name="myStudent",autowire=Autowire.BY_TYPE)
public Student initialStudent(){
return new Student("张三",23);
}
}
B: byName方式的域属性自动注入
// 该注解表示:本类为JavaConfig
@Configuration
public class MyJavaConfig{
// 由于Student的School属性采用byName方式,并要将这里定义的对象赋值给School属性,所以要求这里的name属性值要与School属性值相同。
@Bean(name="mySchool")
public School initialSchool(){
return new School("清华大学");
}
// 采用byName自动注入school属性。要求School名要与JavaConfig中定义某Bean的name属性值相同。
@Bean(name="myStudent",autowire=Autowire.BY_NAME)
public Student initialStudent(){
return new Student("张三",23);
}
}