一、依賴注入
Spring 從核心而言,是一個DI 容器,其設計哲學是提供一種無侵入式的高擴展性框架。即無需代碼中涉及Spring專有類,即可將其納入Spring容器進行管理。作為對比,EJB則是一種高度侵入性的框架規(guī)范,它制定了眾多的接口和編碼規(guī)范,要求實現(xiàn)者必須遵從。侵入性的后果就是,一旦系統(tǒng)基于侵入性框架設計開發(fā),那么之后任何脫離這個框架的企圖都將付出極大的代價。為了避免這種情況,實現(xiàn)無侵入性的目標。Spring 大量引入了Java 的Reflection機制,通過動態(tài)調(diào)用的方式避免硬編碼方式的約束,并在此基礎(chǔ)上建立了其核心組件BeanFactory,以此作為其依賴注入機制的實現(xiàn)基礎(chǔ)。org.springframework.beans包中包括了這些核心組件的實現(xiàn)類,核心中的核心為BeanWrapper和BeanFactory類。這兩個類從技術(shù)角度而言并不復雜,但對于Spring 框架而言,卻是關(guān)鍵所在。
1、Spring兩種屬性注入的方式:
1.set方式注入
<bean id="user" class="com.spring.demo1.User" scope="singleton">
<!-- 注入屬性值 name的屬性值就是類里面定義的屬性名稱 value設置具值-->
<property name="bookname" value="程序設計"></property>
</bean>
2.有參構(gòu)造注入
<bean id="user1" class="com.boss.domain.User1">
<constructor-arg name="username" value="李四" />
</bean>
2、手寫依賴注入(Set方式注入底層原理)
要想實現(xiàn)依賴注入,首先我們需要在BeanDefinition中定義屬性的鍵值對:
實際BeanDefinition中存放對象屬性的是BeanDefinition的propertyValues屬性,它是一個列表,存放的是包含有對象屬性信息的對象:PropertyValue
//存放屬性鍵值對
private Map<String, String> propertyMap = new HashMap<>(16);
在BeanFactory中返回實例化對象前,給對象賦值。實現(xiàn)setvalue方法:
private void setValue(Object instance, Class beanField, Map<String, String> propertyMap) throws Exception {
//獲取所有的方法
Method[] methods = beanField.getDeclaredMethods();
//對properMap進行解析,獲取鍵值對,也就是需要注入的屬性和屬性值
Set<String> propertySet = propertyMap.keySet();
Iterator<String> propertyIterator = propertySet.iterator();
while (propertyIterator.hasNext()){
String propertyKey = propertyIterator.next();
String propertyValue = propertyMap.get(propertyKey);
//獲取的屬性
Field field = beanField.getDeclaredField(propertyKey);
//屬性對應的set方法
String methodName = "set" + field.getName();
//對方法進行過濾
for (int i = 0; i < methods.length; i ++){
Method method = methods[i];
if (methodName.equalsIgnoreCase(method.getName())){
//判斷set方法的類型 也就是屬性的類型
Class fieldType = field.getType();
if (fieldType == String.class){
method.invoke(instance, propertyValue);
} else if (fieldType == Integer.class){
method.invoke(instance, Integer.valueOf(propertyValue));
//這里只對List類型做判斷
} else if (fieldType == List.class){
List<String> tmpList = new ArrayList<>(16);
String[] itemArray = propertyValue.split(",");
for (int j = 0; j < itemArray.length; j ++){
tmpList.add(itemArray[i]);
}
}else {
throw new RuntimeException("暫不該支持屬性類型注入");
}
}
}
}
}
實現(xiàn)邏輯不難,就是一層一層解析,基本步驟可以看注解。測試類:TestMain
@Test
public void testPropertyMap() throws Exception {
//注冊bean
BeanDefined beanObj = new BeanDefined();
beanObj.setBeanId("user");
beanObj.setClassPath("com.lks.bean.User");
//設置propertyMap 類似Spring中依賴注入屬性值
Map<String, String> propertyMap = beanObj.getPropertyMap();
propertyMap.put("name", "蕭峰");
propertyMap.put("age", "31");
propertyMap.put("sex", "男");
List<BeanDefined> beanDefineds = new ArrayList<>(16);
beanDefineds.add(beanObj);
//聲明BeanFactory,類似于Spring中的ApplicationContext
BeanFactory factory = new BeanFactory(beanDefineds);
//實際調(diào)用
User user = (User) factory.getPropertyBean("user");
System.out.println(user.toString());
}
3、BeanDefinition擴展


BeanDefinitionBuilder已經(jīng)是最頂層應用,可以利用BeanDefinitionBuilder生成BeanDefinition:
BeanDefinition beanDefinition= BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
BeanDefinition屬性內(nèi)容:

二、Bean的生命周期

https://www.cnblogs.com/liurg/p/7942374.html
屬性注入的形式:
基于XML
基于?
手寫依賴注入:
https://blog.csdn.net/lks1139230294/article/details/88201149
什么是IOC
https://www.cnblogs.com/XiOrang/p/9337991.html
依賴注入與自動裝配的關(guān)系
https://blog.csdn.net/qq_20367813/article/details/80940366
自動裝配的方式有哪些?
https://www.pianshen.com/article/294442824/
AOP實戰(zhàn)
抽象方法與多態(tài):
動態(tài)代理底層原理
Autowired的底層:getBean
動態(tài)代理底層邏輯
如何進行屬性填充:
http://www.itdecent.cn/p/20cf0116c5c0