Spring源碼深度解析,Spring源碼以及組件(六)(附代碼示例:Cap9)
目錄
Spring源碼深度解析,Spring源碼以及組件(六)(附代碼示例:Cap9)
二,@Autowired ,即自動裝配, spring 利用依賴注入(Di) 完成對IOC容器中的各個組件的依賴關係賦值,並且對 bean 的 加載優先級做處理,
3.1, @Resource 和 @Autowired 一樣都可以裝配bean。 缺點:不能支持 @Primary功能,@Autowired(requied = false ) 的功能 。
一,@Value,即一般都是給 類的 屬性 賦值
1.1,示例代碼:通過給 User 類 賦值, Cap9 項目源碼
sex 這個屬性, 是通過 properties 文件注入的。 @PropertySource 會把文件去交給 Spring 去掃描,去注入到容器,會加載到 Spring 裏面有個類, 環境變量中。
ConfigurableEnvironment environment = applicationContext.getEnvironment();
通過從環境變量中直接取到 user.sex 的值
environment.getProperty("user.sex")
@PropertySource(value = {"classpath:/test.properties"})
@Configuration
public class Cap9MainConfig {
@Bean
public User user(){
return new User();
}
}
properties 文件:
user.sex = 22
自定義 User 類: 通過 註解 @Value 賦值 初始化 屬性。
public class User {
@Value("張三")
private String name;
@Value("30")
private int age;
@Value("${user.sex}")
private String sex;
public User() {
}
public User(String name, int age,String sex) {
super();
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age + '\'' +
", sex=" + sex +
'}';
}
}
測試:
@Test
public void test(){
//將配置類添加到容器中
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Cap9MainConfig.class);
User user = (User) applicationContext.getBean("user");
System.out.println(user);
//properties 會加載到環境變量中,那麼可以從環境變量裏直接取 user.sex 的值
ConfigurableEnvironment environment = applicationContext.getEnvironment();
System.out.println("environment=====>" + environment.getProperty("user.sex"));
//關閉容器
applicationContext.close();
}
二,@Autowired ,即自動裝配, spring 利用依賴注入(Di) 完成對IOC容器中的各個組件的依賴關係賦值,並且對 bean 的 加載優先級做處理。
2.1,@ Autowired 代碼示例: Cap9 項目源碼
聲明一個 UserDao
public class UserDao {
@Value("1")
private String flag;
public UserDao() {
}
public String getFlag() {
return flag;
}
public void setFlag(String flag) {
this.flag = flag;
}
@Override
public String toString() {
return "UserDao{" +
"flag='" + flag + '\'' +
'}';
}
}
聲明一個 業務類。。 使用 註解 @Auto wired 裝配到容器中,這裏有一個地方,需要注意一下 required 這個屬性
下面是 @Autowired 註解 源碼,
也就是說, 在我們使用@Autowired 註解裝配 bean 的時候, @Autowired 源碼 required 屬性默認爲 ture, 也就是說 Spring 容器中必須存在 @Autowired 註解 準備 裝配的 Bean, 當然 required 屬性 也可以設置爲 false ,就是忽略。
注①: 如果你沒有註冊 Bean , 而去 使用 類似@Autowired 註解 去裝配,會出現下面的異常:
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService': Unsatisfied dependency expressed through field 'userDao'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.enjoy.Cap9.Dao.UserDao' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService': Unsatisfied dependency expressed through field 'userDao'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.enjoy.Cap9.Dao.UserDao' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
注②:如果你忘記註冊, 而 使用 @Autowired (required =false) 裝配的時候忽略沒有註冊到容器的bean, 打印出來的 Bean 實例 會是 null 沒有實例化的, 也不會出現什麼異常。
這也是 @Autowired 與 @ Recource 註解 區別 之一。 @Recource 是容器必須有註冊了Bean, 沒有屬性 設置。沒有就拋異常
@Service
public class UserService {
@Autowired(required = false)
private UserDao userDao;
/**
* 測試是否已經自動裝配
*/
public void println() {
System.out.println(userDao);
}
}
以下是配置類:
@ComponentScan({"com.enjoy.Cap9.*"}) //掃描Cap9,下面所有的包
public class Cap9Main2Config {
@Bean
public UserDao userDao(){
return new UserDao();
}
}
2.2,@Qualifier, 指定裝配組件id 進行加載
2.3,@Primary,優先加載指定Bean
三,@Resource(JSR250), 也是自動裝配,但是 在功能上並沒有 Autowired 支持的那麼好。
3.1, @Resource 和 @Autowired 一樣都可以裝配bean。 缺點:不能支持 @Primary功能,@Autowired(requied = false ) 的功能 。
四,@Inject(JSR330), 即自動裝配,不是 Spring 框架的依賴。
4.1,@inject 與 @Autowired 一樣可以裝配 Bean ,並支持 @Primary功能,可用於非Spring 框架。 缺點: 不能支持 @Autowired(requied = false ) 的功能, 需要引入第三方包 javax.inject
五,項目Demo地址
Spring源碼深度解析,(附代碼示例 碼雲地址: https://gitee.com/Crazycw/SpringCode.git)
參考資料: https://docs.spring.io/spring/docs/4.3.18.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/
請看下篇: Spring源碼深度解析,Spring核心技術 Aop,詳解 Aop(七)(附代碼示例:)