挂面01

2019-09-24  本文已影响0人  盼旺

1.DNS原理及其解析过程

为什么?
网络通讯大部分是基于TCP/IP的,而TCP/IP是基于IP地址的,所以计算机在网络上进行通讯时只能识别如“202.96.134.133”之类的IP地址,而不能认识域名。
过程

1) 浏览器缓存  
当用户通过浏览器访问某域名时,浏览器首先会在自己的缓存中查找是否有该域名对应的IP地址
(若曾经访问过该域名且没有清空缓存便存在); 
2) 系统缓存  
当浏览器缓存中无域名对应IP则会自动检查用户计算机系统Hosts文件DNS缓存是否有该域名对应IP;  
Linux下面的位置/etc/hosts windows下C:\Windows\System32\drivers\etc
3) 路由器缓存  
当浏览器及系统缓存中均无域名对应IP则进入路由器缓存中检查,以上三步均为客服端的DNS缓存;  
4) ISP(互联网服务提供商)DNS缓存  
当在用户客服端查找不到域名对应IP地址,则将进入ISP DNS缓存中进行查询。
比如你用的是电信的网络,则会进入电信的DNS缓存服务器中进行查找;  
5) 根域名服务器  
当以上均未完成,则进入根服务器进行查询。全球仅有13台根域名服务器,
1个主根域名服务器,其余12为辅根域名服务器。
根域名收到请求后会查看区域文件记录,若无则将其管辖范围内顶级域名(如.com)服务器IP告诉本地DNS服务器;  
6) 顶级域名服务器  
顶级域名服务器收到请求后查看区域文件记录,若无则将其管辖范围内主域名服务器的IP地址告诉本地DNS服务器;  
7) 主域名服务器  
主域名服务器接受到请求后查询自己的缓存,如果没有则进入下一级域名服务器进行查找,
并重复该步骤直至找到正确纪录;  
8)保存结果至缓存  
本地域名服务器把返回的结果保存到缓存,以备下一次使用,
同时将该结果反馈给客户端,客户端通过这个IP地址与web服务器建立链接

DNS几级域名?

www.   zhihu.  com     .
三级域 二级域 顶级域 根域
www.   zhihu. com.   cn      .
四级域 三级域 二级域 顶级域 根域
说明:根域是后面的点(.)

2.使用Spring框架的好处

轻量:Spring 是轻量的,基本的版本大约2MB。

控制反转IOC:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,
而不是创建或查找依赖的对象们。

面向切面的编程(AOP):Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。

容器:Spring 包含并管理应用中对象的生命周期和配置。

MVC框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。

事务管理:Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA)。

异常处理:Spring 提供方便的API把具体技术相关的异常
(比如由JDBC,Hibernate or JDO抛出的)转化为一致的unchecked 异常。

3.spring ioc原理

IOC控制反转:说的是创建对象实例的控制权从代码控制剥离到IOC容器控制,实际上就是我们现在说的第三方

Spring容器高层视图
Spring 启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相应的Bean配置注册表,然后根据这张注册表实例化Bean,装配好Bean之间的依赖关系,利用 Java 语言的反射功能实例化 Bean 并建立 Bean 之间的依赖关系。为上层应用提供准备就绪的运行环境。 Spring 的 IoC 容器在完成这些底层工作的基础上,还提供了 Bean 实例缓存、生命周期管理、 Bean 实例代理、事件发布、资源装载等高级服务。
IOC容器设计中,两个主要的接口
BeanFactory
ApplicationContext
我们一般称BeanFactory为IoC容器,而称ApplicationContext为应用上下文或Spring容器。
对于BeanFactory 和 ApplicationContext的用途:
1.BeanFactory是Spring框架的基础设施,面向Spring本身
它是一个类的通用工厂,可以创建并管理各种类的对象。
这些被创建和管理的对象,并无特别之处,仅仅是一个POJO。
BeanFactory的主要方法是 getBean(String beanName). 该方法从容器中返回特定名称的Bean
2.ApplicationContext面向使用Spring框架的开发者,直接使用Application而非底层的BeanFactory.

4.Java反射机制在Spring IOC中的应用

IOC底层实现的原理(反射)
在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作为传入参数 -->
     <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将会作为传入参数
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提倡的就是面向接口编程,所以先定义接口StudentDaoStudentService ,让我们的具体实现类实现接口,里面假设有一个添加学生的方法
3.实现类StudentDaoImp implements StudentDaoStudentServiceImpimplements 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的底层其实就是利用反射机制实现的,他把dao注入进来,其实底层就是通过反射set进来的。

4.下一步我们就是定义我们自己的ClassPathXmlApplicationContext类了,通过他,在我们new出他的对象的时候,他来加载配置文件,然后把我们的dao操作注入到我们的service层

在spring中,ClassPathXmlApplicationContext类实现了BeanFactory接口,在此我们也定义一个BeanFactory接口,其实这个接口没什么具体的作用,我们就是为了来模拟spring。
BeanFactory接口其实很简单,就定义了一个getBean方法,提供的bean的id,从bean容器内把对应的bean取出来。

public interface BeanFactory {  
public Object getBean(String id);  
}

5.在定义实现类之前,我们先来看一下我们所需的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.具体的实现类

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

上一篇下一篇

猜你喜欢

热点阅读