1.DNS原理及其解析過程
為什么皮壁?
網絡通訊大部分是基于TCP/IP的,而TCP/IP是基于IP地址的,所以計算機在網絡上進行通訊時只能識別如“202.96.134.133”之類的IP地址缴守,而不能認識域名宏浩。
過程
1) 瀏覽器緩存
當用戶通過瀏覽器訪問某域名時礼仗,瀏覽器首先會在自己的緩存中查找是否有該域名對應的IP地址
(若曾經訪問過該域名且沒有清空緩存便存在)甩苛;
2) 系統(tǒng)緩存
當瀏覽器緩存中無域名對應IP則會自動檢查用戶計算機系統(tǒng)Hosts文件DNS緩存是否有該域名對應IP;
Linux下面的位置/etc/hosts windows下C:\Windows\System32\drivers\etc
3) 路由器緩存
當瀏覽器及系統(tǒng)緩存中均無域名對應IP則進入路由器緩存中檢查赏参,以上三步均為客服端的DNS緩存志笼;
4) ISP(互聯(lián)網服務提供商)DNS緩存
當在用戶客服端查找不到域名對應IP地址,則將進入ISP DNS緩存中進行查詢登刺。
比如你用的是電信的網絡籽腕,則會進入電信的DNS緩存服務器中進行查找;
5) 根域名服務器
當以上均未完成纸俭,則進入根服務器進行查詢皇耗。全球僅有13臺根域名服務器,
1個主根域名服務器揍很,其余12為輔根域名服務器郎楼。
根域名收到請求后會查看區(qū)域文件記錄,若無則將其管轄范圍內頂級域名(如.com)服務器IP告訴本地DNS服務器窒悔;
6) 頂級域名服務器
頂級域名服務器收到請求后查看區(qū)域文件記錄呜袁,若無則將其管轄范圍內主域名服務器的IP地址告訴本地DNS服務器;
7) 主域名服務器
主域名服務器接受到請求后查詢自己的緩存简珠,如果沒有則進入下一級域名服務器進行查找阶界,
并重復該步驟直至找到正確紀錄;
8)保存結果至緩存
本地域名服務器把返回的結果保存到緩存聋庵,以備下一次使用膘融,
同時將該結果反饋給客戶端,客戶端通過這個IP地址與web服務器建立鏈接
DNS幾級域名祭玉?
www. zhihu. com .
三級域 二級域 頂級域 根域
www. zhihu. com. cn .
四級域 三級域 二級域 頂級域 根域
說明:根域是后面的點(.)
2.使用Spring框架的好處
輕量:Spring 是輕量的氧映,基本的版本大約2MB。
控制反轉IOC:Spring通過控制反轉實現(xiàn)了松散耦合脱货,對象們給出它們的依賴岛都,
而不是創(chuàng)建或查找依賴的對象們。
面向切面的編程(AOP):Spring支持面向切面的編程振峻,并且把應用業(yè)務邏輯和系統(tǒng)服務分開臼疫。
容器:Spring 包含并管理應用中對象的生命周期和配置。
MVC框架:Spring的WEB框架是個精心設計的框架扣孟,是Web框架的一個很好的替代品烫堤。
事務管理:Spring 提供一個持續(xù)的事務管理接口,可以擴展到上至本地事務下至全局事務(JTA)。
異常處理:Spring 提供方便的API把具體技術相關的異常
(比如由JDBC塔逃,Hibernate or JDO拋出的)轉化為一致的unchecked 異常。
3.spring ioc原理
IOC控制反轉:說的是創(chuàng)建對象實例的控制權從代碼控制剝離到IOC容器控制料仗,實際上就是我們現(xiàn)在說的第三方
Spring 啟動時讀取應用程序提供的Bean配置信息湾盗,并在Spring容器中生成一份相應的Bean配置注冊表,然后根據(jù)這張注冊表實例化Bean立轧,裝配好Bean之間的依賴關系格粪,利用 Java 語言的反射功能實例化 Bean 并建立 Bean 之間的依賴關系。為上層應用提供準備就緒的運行環(huán)境氛改。 Spring 的 IoC 容器在完成這些底層工作的基礎上帐萎,還提供了 Bean 實例緩存、生命周期管理胜卤、 Bean 實例代理疆导、事件發(fā)布、資源裝載等高級服務葛躏。
IOC容器設計中澈段,兩個主要的接口
BeanFactory
ApplicationContext
我們一般稱BeanFactory為IoC容器,而稱ApplicationContext為應用上下文或Spring容器舰攒。
對于BeanFactory 和 ApplicationContext的用途:
1.BeanFactory是Spring框架的基礎設施败富,面向Spring本身
它是一個類的通用工廠,可以創(chuàng)建并管理各種類的對象摩窃。
這些被創(chuàng)建和管理的對象兽叮,并無特別之處,僅僅是一個POJO猾愿。
BeanFactory的主要方法是
getBean(String beanName)
. 該方法從容器中返回特定名稱的Bean2.ApplicationContext面向使用Spring框架的開發(fā)者鹦聪,直接使用Application而非底層的BeanFactory.
4.Java反射機制在Spring IOC中的應用
IOC底層實現(xiàn)的原理(反射)
在Spring的配置文件中,經撤梭埃看到如下配置
<bean id="courseDao" class="com.qcjy.learning.Dao.impl.CourseDaoImpl"></bean>
Spring是怎么幫我們實例化對象椎麦,并且放到容器中去了?
對材彪,就是通過反射.
偽代碼
//解析<bean .../>元素的id屬性得到該字符串值為“courseDao”
String idStr = "courseDao";
//解析<bean .../>元素的class屬性得到該字符串值為“com.qcjy.learning.Dao.impl.CourseDaoImpl”
String classStr = "com.qcjy.learning.Dao.impl.CourseDaoImpl";
//利用反射知識观挎,通過classStr獲取Class類對象
Class<?> cls = Class.forName(classStr);
//實例化對象
Object obj = cls.newInstance();
//container表示Spring容器
container.put(idStr, obj);
通過解析xml文件,獲取到id屬性和class屬性里面的內容段化,利用反射原理Class.froName()
獲取到配置里面類的實例對象嘁捷,存入到Spring的bean容器中。
當一個類里面需要應用另一類的對象時显熏,Spring的配置如下所示:
<bean id="courseService" class="com.qcjy.learning.service.impl.CourseServiceImpl">
<!-- 控制調用setCourseDao()方法雄嚣,將容器中的courseDao bean作為傳入參數(shù) -->
<property name="courseDao" ref="courseDao"></property>
</bean>
偽代碼
//解析<property .../>元素的name屬性得到該字符串值為“courseDao”
String nameStr = "courseDao";
//解析<property .../>元素的ref屬性得到該字符串值為“courseDao”
String refStr = "courseDao";
//生成將要調用setter方法名
String setterName = "set" + nameStr.substring(0, 1).toUpperCase()
+ nameStr.substring(1);
//獲取spring容器中名為refStr的Bean,該Bean將會作為傳入參數(shù)
Object paramBean = container.get(refStr);
//獲取setter方法的Method類,此處的cls是剛才反射代碼得到的Class對象
Method setter = cls.getMethod(setterName, paramBean.getClass());
//調用invoke()方法缓升,此處的obj是剛才反射代碼得到的Object對象
setter.invoke(obj, paramBean);
只要在代碼或配置文件中看到類的完整路徑(包.類)鼓鲁,其底層原理基本上使用的就是Java的反射機制
5.可以自己寫一個spring IOC
1.假設有一個Student.java
public class Student {
private int id;
private String name;
******************set、get方法省略
}
2.因為spring提倡的就是面向接口編程港谊,所以先定義接口StudentDao
和StudentService
骇吭,讓我們的具體實現(xiàn)類實現(xiàn)接口,里面假設有一個添加學生的方法
3.實現(xiàn)類StudentDaoImp implements StudentDao
和StudentServiceImp
implements StudentService`
public class StudentDaoImp implements StudentDao {
public void add(Student stu) {
System.out.println("stu is saved");
}
}
public class StudentServiceImp implements StudentService {
StudentDao stuDao=null;
public StudentDao getStuDao() {
return stuDao;
}
public void setStuDao(StudentDao stuDao) {
this.stuDao = stuDao;
}
@Override
public void add(Student stu) {
stuDao.add(stu);
}
}
模擬spring中的IOC功能,所以在此我們一樣要在service層中定義dao的實例歧寺,當然不用new出來
不要忘了對dao提供set燥狰。get方法,因為IOC的底層其實就是利用反射機制實現(xiàn)的斜筐,他把dao注入進來龙致,其實底層就是通過反射set進來的。
4.下一步我們就是定義我們自己的ClassPathXmlApplicationContext
類了顷链,通過他目代,在我們new出他的對象的時候,他來加載配置文件嗤练,然后把我們的dao操作注入到我們的service層
在spring中像啼,
ClassPathXmlApplicationContext
類實現(xiàn)了BeanFactory
接口,在此我們也定義一個BeanFactory
接口潭苞,其實這個接口沒什么具體的作用忽冻,我們就是為了來模擬spring。
BeanFactory接口其實很簡單此疹,就定義了一個getBean方法,提供的bean的id僧诚,從bean容器內把對應的bean取出來。
public interface BeanFactory {
public Object getBean(String id);
}
5.在定義實現(xiàn)類之前蝗碎,我們先來看一下我們所需的xml是怎么編寫的湖笨,
下面我們就具體來看一下beans.xml
的配置(它用來表示Bean對象與Bean對象之間的依賴關系):
<beans>
<bean id="stuDao" class="com.bzu.dao.imp.StudentDaoImp" />
<bean id="stuService" class="com.bzu.service.imp.StudentServiceImp" >
<property name="stuDao" bean="stuDao"/>
</bean>
</beans>
6.具體的實現(xiàn)類
public class ClassPathXmlApplicationContext implements BeanFactory{
private Map<String, Object> beans = new HashMap<String,Object>();
public ClassPathXmlApplicationContext() throws Exception,Exception {
SAXBuilder sb = new SAXBuilder();
Document doc = sb.build(this.getClass().getClassLoader()
.getResourceAsStream("beans.xml")); // 構造文檔對象
Element root = doc.getRootElement(); // 獲取根元素HD
List list = root.getChildren("bean");// 取名字為bean的所有元素
for (int i = 0; i < list.size(); i++) {
Element element = (Element) list.get(i);
String id = element.getAttributeValue("id");
String clazz = element.getAttributeValue("class");
Object o = Class.forName(clazz).newInstance();
System.out.print("bean id is " + id);
System.out.println(", clazz is " + clazz);
beans.put(id, o);
// 遍歷property
for (Element propertyElement : (List<Element>) element
.getChildren("property")) {
String name = propertyElement.getAttributeValue("name");// userDAO
String bean = propertyElement.getAttributeValue("bean");// u
Object beanObject = beans.get(bean);// UserDAOImpl instance
// 構造setter方法
String methodName = "set" + name.substring(0,1).toUpperCase()
+ name.substring(1);
System.out.println("setter method name = " +methodName);
Method m = o.getClass().getMethod(methodName,
beanObject.getClass().getInterfaces()[0]);
m.invoke(o, beanObject);
}
}
}
@Override
public Object getBean(String id) {
return beans.get(id);
}
}
首先我們定義了一個容器Map<String, Object> beans
,這個容器的作用就是用來裝我們從配置文件里解析來的一個個bean蹦骑,為什么要用map類型慈省,我想大家也差不多能猜到吧,我們配置文件中每一個bean都有一個id來作為自己的唯一身份眠菇。我們把這個id存到map的key里面边败,然后value就裝我們的具體bean對象
ClassPathXmlApplicationContext的構造方法,這個構造方法是我們spring管理容器的核心捎废,這個構造方法的前半部分是利用的jdom解析方式笑窜,把xml里面的bean一個個的解析出來,然后把解析出來的bean在放到我們bean容器里登疗。后半部分主要是在對配置文件進行解析出bean的同時去查看一下這個bean中有沒有需要注射bean的排截,如果有的話嫌蚤,他就去通過這些里面的property屬性獲取他要注射的bean名字,然后構造出set方法断傲,然后通過反射脱吱,調用注入bean的set方法,這樣我們所需要的bean就被注入進來了认罩。
7.測試spring到底能不能自動把我們所需要的dao層注入給service急凰。
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
Student stu = new Student();
StudentService service = (StudentService) context.getBean("stuService");
service.add(stu);
}
參考文章https://blog.csdn.net/mlc1218559742/article/details/52774805