挂面01
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)
. 该方法从容器中返回特定名称的Bean2.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提倡的就是面向接口编程,所以先定义接口StudentDao
和StudentService
,让我们的具体实现类实现接口,里面假设有一个添加学生的方法
3.实现类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的底层其实就是利用反射机制实现的,他把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