[3]Spring 5 注解编程基础组件-赋值类注解
连载地址
总览、赋值组件 Injection Components

一、@Component 注解
1.1 功能说明
泛指组件,当组件不好归类的时候,使用这个注解进行标注
1.2 要点说明
从源码可以看出,@Service
、@Repository
、@Controller
、Configuration
等组件都是@Component
组件的一种,他们都使用了@Component
组件。
1.3 源码
@Component
注解源码
package org.springframework.stereotype;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
String value() default "";
}
1.4 demo
@Component
public class MyConponent {
//声明这个类需要被注册到IOC容器中
}
二、@Service 注解
2.1 功能说明
用于标注业务层组件
2.2 源码
package org.springframework.stereotype;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
@AliasFor(
annotation = Component.class
)
String value() default "";
}
2.3 demo
@Service
public class MyService {
//如果是业务层组件,则用此注解,同样会被注册到IOC容器中
}
三、@Controller 注解
3.1 功能说明
用于标注控制层组件
3.2 源码
package org.springframework.stereotype;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
@AliasFor(
annotation = Component.class
)
String value() default "";
}
3.3 demo
@Controller
public class MyController {
// 如果是控制层组件,则用此注解,同样会被注册到IOC容器中
}
四、@Repository 注解
4.1 功能说明
用于标注数据访问层组件,即DAO组件
4.2 源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
@AliasFor(
annotation = Component.class
)
String value() default "";
}
4.3 demo
@Repository
public class MyDao {
// 如果是数据访问层组件,则用此注解,同样会被注册到IOC容器中
}
五、@Value 注解
5.1 功能说明
普通数据类型赋值
5.2 要点说明
三种使用@Value的方式给属性赋值:
- 直接赋值
- 获取配置文件属性
- EL表达式
5.3 源码
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {
String value();
}
5.4 demo
5.4.1 代码
@Component
public class Player {
//支持基本数据类型
@Value("AlanChen")
private String name;
//通过@PropertySource("classpath:values.properties")读取配置文件取值
@Value("${player.address}")
private String address;
//支持Spring EL表达式
@Value("#{2022-1990}")
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Player{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
", age=" + age +
'}';
}
}
@Configuration
@ComponentScan
@PropertySource("classpath:values.properties")
public class MyConfig {
// @ComponentScan注解在某类上时会扫描该类所在包下的所有类
}
public class MyTest {
@Test
public void test(){
ApplicationContext app = new AnnotationConfigApplicationContext(MyConfig.class);
Player player = app.getBean(Player.class);
System.out.println(player);
}
}
resources/values.properties
player.address=Zhu Hai
5.4.2 运行结果
Player{name='AlanChen', address='Zhu Hai', age=32}
六、@PropertySource 注解
6.1 功能说明
读取配置文件赋值
6.2 源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {
String name() default "";
String[] value();
boolean ignoreResourceNotFound() default false;
String encoding() default "";
Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
}
6.3 demo
6.3.1 代码
@Configuration
@ComponentScan
@PropertySource("classpath:values.properties")
public class MyPropertySourceConfig {
// @ComponentScan注解在某类上时会扫描该类所在包下的所有类
}
public class MyTest {
@Test
public void test() {
ApplicationContext app = new AnnotationConfigApplicationContext(MyPropertySourceConfig.class);
System.out.println("IoC容器创建完成");
// 从环境变量中取值
Environment env = app.getEnvironment();
String address = env.getProperty("player.address");
System.out.println(address);
}
}
6.3.2 运行结果
IoC容器创建完成
Zhu Hai
七、@Autowired 注解
7.1 功能说明
用来完成组件的装配,可以结合@Qualifier
注解一起使用组件的装配。
7.2 要点说明
-
@Autowired
为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired
。 - 默认按byType自动注入,是Spring的注解。
- 默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,@Autowired(required = false)。
- 按类型装配的过程中,如果发现找到多个bean,则又按照byName方式进行比对,如果还有多个,则报出异常。
7.3 源码
package org.springframework.beans.factory.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
7.4 demo
@Repository
public class UserDao {
}
@Service
public class UserService {
@Autowired
private UserDao userDao;
}
八、@Qualifier 注解
8.1 功能说明
如存在多个实例,配合@Autowired使用,优先级高于@Autowired,但是无法单独使用。如存在多个实例,配合使用,优先级高于@Autowired
8.2 源码
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
String value() default "";
}
8.3 demo
@Repository("dao")
public class StudentDao {
}
@Service
public class StudentService {
@Qualifier("dao")
@Autowired
private StudentDao studentDao;
}
九、@Primary 注解
9.1 功能说明
如果Spring容器中存在多个相同名字的Bean,使用@Primary注解可以提高优先级,成为首选者,否则报错。
9.2 源码
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Primary {
}
9.3 demo
9.3.1 代码
public class SchoolComponent {
private String name;
public SchoolComponent() {
}
public SchoolComponent(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "SchoolComponent{" +
"name='" + name + '\'' +
'}';
}
}
@Configuration
@ComponentScan
public class MyPrimaryConfig {
//使用当前实例
@Primary
@Bean("schoolComponent")
public SchoolComponent schoolComponent() {
return new SchoolComponent("清华");
}
@Bean("schoolComponent")
public SchoolComponent schoolComponent2() {
return new SchoolComponent("北大");
}
}
public class MyTest {
@Test
public void test(){
ApplicationContext app = new AnnotationConfigApplicationContext(MyPrimaryConfig.class);
Object bean = app.getBean("schoolComponent");
System.out.println(bean);
}
}
9.3.2 运行结果
SchoolComponent{name='清华'}
十、@Resource 注解
10.1 功能说明
用来完成组件的装配,可以单独使用,优先级更高。
10.2 要点说明
-
@Resource
是javaEE的注解,它遵循的是JSR-250规范,需要导入包javax.annotation.Resource
。 -
默认按照byName方式进行装配,属于J2EE自带注解,没有指定name时,name指的是变量名。
-
如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
-
如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
-
如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常。
-
如果既没有指定name,又没有指定type,则自动按照byName方式进行装配。如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。
10.3 源码
package javax.annotation;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface Resource {
String name() default "";
String lookup() default "";
Class<?> type() default java.lang.Object.class;
enum AuthenticationType {
CONTAINER,
APPLICATION
}
AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
boolean shareable() default true;
String mappedName() default "";
String description() default "";
}
10.4 demo
@Repository("addressDao")
public class UserAddressDao {
}
@Service
public class UserAddressService {
@Resource(name = "address")
private UserAddressDao userAddressDao;
}