技术标签: Spring(+注解开发)&&SpringMVC
IOC全名是inversion of control ,就是反转控制,也叫控制反转,其实它也不是听得那么高达上,其实就是一种思想,
之前我们创建类后需要new对象,对象的创建的控制权是在我们程序员的手上,现在我们将创建对象的权力交给spring,我们不需要知道对象是如何创建的,只知道需要向spring要对象使用就行,这样提高了开发的效率
这种将创建对象的权力交给spring的思想就是反转控制
DI全名是dependency injection ,也叫依赖注入
这里就是顾名思义,依赖就是一个对象的创建需要什么对象,比如上面的例子,如果一个person的创建必须要id和name两个属性,那么在创建person对象前就必须先new出id和name两个对象,然后在这两个对象的基础上创建person对象,这就是依赖
而注入就是spring根据对象的创建需要什么就注入什么,比如上面需要id和name,那么就会给你id和name
其实IOC就是一种反转控制的思想,而DI就是IOC这种思想的具体实现
package jane;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test
{
public static void main(String[] args)
{
/*
* 初始化容器,ApplicationContext是一个接口,我们需要用它的实现类来创建容器
* ClassPathXmlApplicationContext里面的参数是配置文件的路径,所以conf里面的
* 配置文件名是可以改的,但是在以后的ssm框架里面是自动初始化容器,会自动找
* applicationContext.xml文件,所以建议还是写成applicationContext.xml
* 在配置文件里面有一个唯一标识的id,这里使用id来得到bean
*/
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
/*
* 这个方法是直接通过bean的id属性进行查找的,
* 因为bean的id是不能重复的,所以这里不会冲突
*/
// Person bean = (Person)ac.getBean("Person");
/*
* 这个方法是通过类来得到bean的,如果使用这个方法,
* 那么确保配置文件里面这个class对应的bean只能有一个,
* 如果这个class有多个bean的时候,就会报错
* Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [jane.Person] is defined: expected single matching bean but found 2: Person1,Person2
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:312)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:985)
at jane.Test.main(Test.java:19)
*/
// Person bean = ac.getBean(Person.class);
/*
* 这个重载的方法就是使用id和类确定bean的位置,这个一般不会有太多问题
* 所以一般我们使用这个
*/
Person bean = ac.getBean("Person1", Person.class);
System.out.println(bean);
/*
* spring能帮我们管理对象,但是spring到底是怎么创建对象的呢?
* 其实我们可以大胆地尝试,之前学过反射,反射创建对象就是先加载
* 这个类,使用class.forname()的方法加载,然后newInstance()创建对象
* 其实spring就是根据反射进行创建对象的,前面配置的bean的class属性
* 就是类的全限定名,就是用来加载类的
* 测试验证:
* 我们如果在person类中写出有参的构造方法,那么无参的构造方法就会被覆盖
* 那么如果spring是反射创建对象的应该会出现错误
* 如我们所愿出现了错误
* Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [jane.Person]: No default constructor found; nested exception is java.lang.NoSuchMethodException: jane.Person.<init>()
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:85)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1069)
... 13 more
Caused by: java.lang.NoSuchMethodException: jane.Person.<init>()
at java.base/java.lang.Class.getConstructor0(Class.java:3354)
at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2558)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:80)
... 14 more
所以spring就是使用反射创建对象的
*/
}
}
spring中最重要的是IOC思想,IOC思想必须基于IOC容器来实现,IOC的最底层实际上就是一个对象工厂,我们来看一下里面的继承关系
最上面的接口就是BeanFactory,就是最基础的东西,而最下面的就是
ClassPathXmlApplicationContext和FileSystemXmlApplicationContext类,
其实这两个类都是一样效果的,
ClassPathXmlApplicationContext是从当前项目的文件中读取配置文件,写的是相对的路径
FileSystemXmlApplicationContext是从系统上读取配置文件,写的是绝对路径,因为有些
项目的配置文件独立地放在一个服务器里面,所以就可以使用这种方法,使用绝对路径
在通过IOC容器读取Bean的实例之前,需要先将IOC容器本身实例化。
Spring提供了IOC容器的两种实现方式
里面有个onfigurableApplicationContext是ApplicationContext的子接口,包含一些扩展方法:refresh()和close()让ApplicationContext具有启动、关闭和刷新上下文的能力。
<bean id="Person1" class="jane.Person">
<property name="id" value="1"></property>
<property name="name" value="张三"></property>
</bean>
比如这里的bean里面,<property name="id" value="1"></property>
是如何给person对象赋值的,
在person类里面,所有的属性都是私有化的,我们访问不了,那么spring是如何赋值
通过追踪查看,原来是调用里面的get和set方法进行赋值
<bean>
<constructor-arg value="3"></constructor-arg>
<constructor-arg value="小红" index="1" type="java.lang.String"></constructor-arg>
</bean>
通过构造方法注入是有个小问题,比如类中的构造方法有多个,例如person类中有两个构造方法public person(Integer id,String name)和public person(Double id,String name)
那么通过这种方法就出现赋值的对象不是你想要的或者报错,那么就需要在constructor-arg
标签里面增加index索引和type类型属性,索引是说明是第几个参数,类型说明它属于什么类型,这种方法不常用,通过set方法注入常用
设置好后这样bean的设置就简单了
直接设置成这样就行<bean id="4" class="jane.Person" p:id="4" p:name="小明"></bean>
<property name="name" value="李四"></property>
这个可以改成
<property name="name">
<value>李四</value>
</property>
<bean id="Person2" class="jane.Person">
<property name="id" value="2"></property>
<property name="name" value="李四"></property>
<property name= "eat" ref ="eat"/>
</bean>
//其中person里面有一个eat类的属性
<bean id="Person2" class="jane.Person">
<property name="id" value="2"></property>
<property name="name" value="李四"></property>
<property name= "eat" ref ="eat"/>
<property name= "eat.run" value="用筷子"/>
</bean>
//这里是在eat类里面有个run的属性,将这个属性赋值为"用筷子"
<bean id="Person2" class="jane.Person">
<property name="id" value="2"></property>
<property name="name" value="李四"></property>
<property name= "eat">
<bean class="jane.run">
<property name="run" value="用筷子"/>
</bean>
</property>
</bean>
//这里是在eat类里面有个run的属性,将这个属性赋值为"用筷子"
<bean id="t1" class="jane.Teacher">
<property name="tid" value="1001"></property>
<property name="tname" value="jane1"></property>
<property name="clas">
<list>
<value>A</value>
<value>B</value>
<value>C</value>
</list>
</property>
</bean>
</bean>
<bean id="t2" class="jane.Teacher">
<property name="tid" value="1002"></property>
<property name="tname" value="jane2"></property>
<property name="students">
<list>
<ref bean="s1"/>
</list>
</property>
</bean>
而数组和list一样,用< array>进行注入,其实数组也可以使用list进行赋值,因为List的底层就是数组,Set使用< set>标签进行注入,定义方法和list一样
这里说下要交给spring管理的类的属性的命名规范,比如sName,不能这样命名属性,因为这样生成的get和set方法不符合set和get方法的规范,生成的get和set方法的属性的名字会弄成大写的,但是sName这样命名就不会变成大写,就直接说没有get和set方法的
<bean id="t3" class="jane.Teacher">
<property name="tid" value="1003"></property>
<property name="tname" value="jane2"></property>
<property name="bossMap">
<map>
<entry>
<key>
<value>1001</value>
</key>
<value>jane1</value>
</entry>
</map>
</property>
</bean>
<bean id="t4" class="jane.Teacher">
<property name="tid" value="10042"></property>
<property name="tname" value="jane4"></property>
<property name="students" ref="list"></property>
</bean>
<util:list id="list">
<ref bean="s1"/>
</util:list>
Spring中有两种类型的bean,一种是普通bean,另一种是工厂bean,就是FactoryBean,不多说,先上代码
//Car类
package factorybean;
public class Car
{
private String brand;
private Double price;
//下面的get和set方法就在这里写了
}
//Myfactory类
package factorybean;
import org.springframework.beans.factory.FactoryBean;
public class Myfactory implements FactoryBean<Car>
{
@Override
public Car getObject() throws Exception
{
Car car=new Car();
car.setBrand("法拉利");
car.setPrice(800000.0);
return car;
}
@Override
public Class<?> getObjectType()
{
return Car.class;
}
@Override
public boolean isSingleton()
{
return false;
}
}
//对应的factory-bean配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="Myfactory" class="factorybean.Myfactory"></bean>
</beans>
//测试类
package factorybean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test
{
public static void main(String[] args)
{
ApplicationContext ac=new ClassPathXmlApplicationContext("factory-bean.xml");
Object bean = ac.getBean("Myfactory");
System.out.println(bean);
}
}
//结果
Car [brand=法拉利, price=800000.0]
Factory Bean就是对象工厂,就是用来产生对象的,我们在bean里面配置工厂的bean,最后运行返回的就是这个工厂对应的的生产的类的对象,就是通过getObject方法得到的
// nth-child(2)$('table tr td:nth-child(2)').css('background-color','red'); // :nth-child(2n)$('table tr td:nth-child(2n)').css('background-color','red'); 演示地址: http://qiaole.sina...
云存储能代替服务器存储吗 内容精选换一换本章节主要介绍云硬盘、弹性文件服务、对象存储服务等存储服务,让您更好的了解这些存储服务。使用存储容灾服务前,请您先了解表1中描述的使用限制。在生产站点可用区整个AZ故障时,可通过容灾演练功能恢复服务器业务。首次切换/故障切换和容灾演练操作后,登录弹性云服务器有哪些注意事项?云存储能代替服务器存储吗 相关内容ModelArts为用户提供了多种常见的预置引擎,但...
1 前言本文主要说明案例中水库下游区域HEC-RAS二维建模的过程。文章首先给出建模的基本原则与建模的注意事项,确定了大致的研究区域。其次,整个下游洪水演进区域由单一二维模型模拟,下游存在一条较大的城市内河,沿河堤线对网格调整加密重生成。HEC-RAS2D建模功能较为丰富,本文远未穷尽全部功能,仅供参考2 建模原则建模的原则其实很简单,首先是针对研究区域分析,确认所有需水动力模拟的现实对象。之后抽...
一、实现效果图二、实现方法 swiper组件主要点在于组件中的 display-multiple-items 属性以及 float: left浮动图标,下面的指示点是另外加的新样式三、事例代码wxml<!--头部导航开始 --><view class="headerModel"> <swiper indicator-dots="{{indicatorDots}}" display-multiple-items="5" bindchange="mddotCh
rpc微服务框架涉及的问题:高效、可靠的调度器同步调用和异步调用的设计适当的发送协议已经解析结果提供不同的服务选择节点的策略-轮询、hash、权重管理服务节点状态,节点是否已连接,是否连接中,是否超时,是否重连,超时时间设置,重连时间设置等,如何可靠的接受请求,发送结果,请求量的控制,接受到1.5个请求怎么办,发送请求,未收到结果怎么办;rpc-client...
Spring中的@Valid 和 @Validated注解文章目录Spring中的@Valid 和 @Validated注解1. 概述2. @Valid和@Validate注解3. 例子4. 使用@Valid批注标记嵌套对象5. 总结1. 概述本文我们将重点介绍Spring中 @Valid和@Validated注解的区别 。验证用户输入是否正确是我们应用程序中的常见功能。Spring提供了@Valid和@Validated两个注解来实现验证功能,下面我们来详细介绍它们。2. @Valid和@Val
一、WinInet简介http://baike.baidu.com/link?url=5JMMt-y0RlKfCRIy3UVXq-pwauKdBi5nvsQ_31ptpHQyS-IHJjJgOuAoYXFF94TYWinInet(“Windows Internet”)API帮助程序员使用三个常见的Internet协议,这三个协议是用于World Wide Web万维网的超文本传输协议(
#编辑JDK8export JAVA_HOME="/usr/java/java8"#编辑mavenexport M2_HOME="/opt/idea-IU-162.1121.32/plugins/maven/lib/maven3"#编辑PATHexport PATH="$JAVA_HOME/bin:$M2_HOME/bin:$PATH"这是我的/etc/profile末尾的
TM和RM初始化过程上一篇文章说过,在Spring启动的过程中就会就会初始化TM和RM,建立与TC的长连接。TM,RM,TC都是用netty来处理网络连接的,初始化netty客户端和服务端的过程也非常类似。本篇文章只分析TM的初始化过程,RM和TM复用了很多方法// TmNettyRemotingClientpublic void init() { // registry processor // 注册消息处理器 registerProcessor(); if (i.
(1)进行linux实战训练的时候,改动了/etc/fstab文件,导致Linux无法正常运行。故障截图;故障原因:我们都知道/etc/fstab 文件识用来挂载分区的,...
import 'package:flutter/cupertino.dart';import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MaterialApp ( title: 'flutter Demo'.
常见模型比较以及应用场景整理