Spring基础入门
一, MVC框架
- MVC全名是Model View Coontroller,是模型(model) 一 视图(view) 一 控制器(controller)的缩写;是一种在开发软件或网站时的思想,设计模式.
- Model 承载数据的抽象结构的数据模型(数据库数据储存在代码中的形式).
- View 视图视图表现层,前端(数据库数据展示).
- controller 控制器(View和Model连接的桥梁,读出写入数据库数据.
- MVC凌驾于语言之上,不是某种语言的专属.
二,Spring框架简单架构介绍
Bean管理 | Spring框架 |
---|---|
持久层操作(操作数据库数据的操作) | MyBatis Hibernate Spring Data jpa |
servlet开发 | Spring 框架 |
微服务 | Dubbo(阿里) Spring Boot 和 Spring Cloud |
缓存 | Redis… |
Spring框架特性
- 轻量
- 从大小与开销两方面而言Spring都是轻量的,完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布.并且Spring所需的处理开销也是微不足道的,此外,Srping是非侵入式的:典型的,Spring应用中的对象不依赖于Spring的特定类
- 控制反转
- Spring通过一种称作控制反转(IOC)的技术促进了低耦合.当应用了IOC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象.可以认为IOC与JNDI相反一不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它
- 面向切面
- Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发.应用对象只实现它们应该做的一完成业务逻辑一仅此而已.它们并不负责其他的系统级关注点
三,Sping名词
-
IOC
- Inversion of Control,控制反转,控制权从应用程序转移到框架.
- 可以吧IOC看作是一个生产和管理bean对象的容器.原本程序中我们要手动自己创建(new)的对象统统交给Spring的IOC容器棒我们创建.同时就意味着,要产生的单例的bean,这个对象的生命周期也是有IOC容器的管理.
-
DI
- 本质上和IOC没有区别,但IOC更偏向于对Bean的控制反转,而DI更偏向于对类中需要使用另外一个类时的依赖注入,进行解耦
-
AOP
- AOP就是将程序功能中的频繁出现或者主业逻辑代码相关度不高的代码抽离出来,通过面向编程的方式在想要调用的时候引入调用的思想.而这种思想并不是只限于Spring和java,AOP(面向切面)和OOP(面向对象)一样都是一种编程思想.这种思想的实现机制在Spring中便是应用了java的动态代理和jav的反射.在调用某个方法之前/后想要自动执行一系列自定义操作的就是AOP思想
-
总结
- IOC即控制反转,一种将控制权转移的设计模式,由传统的程度控制转移到容器控制
- DI即依赖注入,将互相依赖的对象分离,在Spring的配制(注解)中描述它们之间的依赖关系,这些依赖关系也只在使用时才被建立
- AOP即面向切面,一种编程思想,OOP的延续,将系统中非核心的业务提取出来,进行单独处理
- Spring的AOP和IOC都是为了解决代码的耦合度的实际应用,使得代码的重用度变高,便于维护.但这些都不是Spring中特有的,我们可以说Spring将他们应用的更灵活.
四,技术栈
- 以前:SSH:Struts2 + Spring +Hibernate
- 现在:SSM:Spring + SpringMVC+ MyBatis
五,搭建Spring环境
-
创建maven项目
-
添加项目依赖
<dependencys> ....... <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.9.RELEASE</version> </dependency> </dependencies>
-
编程测试代码
-
编写配置文件
-
执行单元测试
六,IOC容器概念
- 可以把IOC看作是一个生产和管理bean对象的容器.原本程序中我们要手动自己创建(new)的对象统统交给Spring的IOC容器棒我们创建.同时就意味着,要产生的单例的bean,这个对象的生命周期也是有IOC容器的管理
七,手动模拟IOC容器
//1.准备一个普通类
package com.shsxt.service;
public class UserService {
public void addUser(){
System.out.println("UserService addUser");
}
}
<!-- 2.在xml文件中配置好配置 -->
<?xml version="1.0" encoding="UTF-8"?>
<beans >
<bean id="userService" class="com.shsxt.service.UserService"></bean>
</beans>
//3.编写核心 加载配置文件类方法
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SxtapplicationContext implements ApplicationContext{
/**
* 1.读取xml并解析
* 2.反射生存bean对象
* 3.返回执行bean
* @param id
* @return
*/
private String xmlPath;//xml配置文件路径
private List<SxtBean> sxtBeanList=new ArrayList<>();//储存解析结果
private Map<String,Object> beanMap=new HashMap<>();//储存反射结果
public SxtapplicationContext(String xmlPath) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
this.xmlPath=xmlPath;
//解析xml
parseXml(xmlPath);
initBean();
}
private void initBean() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
if(sxtBeanList.size() > 0){
for(SxtBean bean:sxtBeanList){
String id=bean.getId();
String clazz=bean.getClazz();
beanMap.put(id,Class.forName(clazz).newInstance());
}
}
}
/**
* 解析xml
* @param
* @return
*/
private void parseXml(String xmlPath){
if(null != xmlPath && !"".equals(xmlPath)){
//使用demo4j技术
//创建解析器对象
SAXReader reader=new SAXReader();
//1.拿到xml
try {
//1.拿到xml配置文件地址 拿到 xml
URL url= this.getClass().getClassLoader().getResource(xmlPath);
Document document=reader.read(url);
//2.解析xml
List<Element> list=document.selectNodes("/beans/bean");
//3.获取属性值
for(Element e:list){
String id=e.attributeValue("id");
String clazz=e.attributeValue("class");
sxtBeanList.add(new SxtBean(id,clazz));
}
} catch (Exception e) {
e.printStackTrace();
}
}else{
System.out.println("文件不存在");
}
}
@Override
public Object getBean(String id) {
return beanMap.get(id);
}
}
//4.编写获取对象方法
package com.shsxt.service;
public class UserService {
public void addUser(){
System.out.println("UserService addUser");
}
}
//5.单元测试
import com.shsxt.service.UserService;
import org.junit.Test;
import static org.junit.Assert.*;
public class ApplicationContextTest {
@Test
public void Test() throws IllegalAccessException, ClassNotFoundException, InstantiationException {
//加载配置文件
ApplicationContext applicationContext=new SxtapplicationContext("spring.xml");
//获取对象
UserService userService= (UserService) applicationContext.getBean("userService");
userService.addUser();
}
}
在简单模拟IOC容器中使用了
- xml解析(dom4j + xpath)
- 反射
- 集合(List Map)
八,多文件加载
- 当有多个xml配置文件时
ApplicationContext ac=new ClassPathXmlApplicationContext("dao.xml","service.xml","controller.xml");
2. 第二种方法,在一个xml中使用import标签,将子配置文件导入到总配置
<?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">
<import resource="dao.xml"/>
<import resource="service.xml"/>
<import resource="controller.xml"/>
</beans>
九,IOC中实例化bean的3种方式
//创建个类
package com.shsxt.dao;
public class HelloDao {
public void hello(){
System.out.println("hello");
}
}
-
构造器的方法实例化bean对象(默认空构造)
<!-- 最常用的实例化方式 --> <bean id="helloDao" class="com.shsxt.dao.HelloDao" ></bean>
-
静态工厂方法方式实例化bean
//首先准备一个静态工厂类,方法要是静态的.缺点,被static修饰的对象方法等都会一直占用内存,一般不是全设置 package com.shsxt; import com.shsxt.service.HelloService; public class PersonService { public static HelloService getHelloService(){ return new HelloService("你好"); } }
<!-- 通过工厂类中的静态方法,来获取到需要的类 --> <bean id="personService" class="com.shsxt.PersonService" factory-method="getHelloService"></bean>
ApplicationContext context1=new ClassPathXmlApplicationContext("spring.xml"); HelloService helloService1= (HelloService) context1.getBean("personService"); helloService1.hello();
-
想比较静态工厂实现
//准备一个工厂类,方法为普通方法,一般适用于框架整合 package com.shsxt.factory; import com.shsxt.service.HelloService; public class InstanceFactory { public HelloService createUserService(){ return new HelloService("工厂模式"); } }
<!-- 首先实例了工程类,然后在选定实例的工厂类中的方法 --> <bean id="instanceFactory" class="com.shsxt.factory.InstanceFactory"></bean> <bean id="helloService" factory-bean="instanceFactory" factory-method="createUserService"></bean>
ApplicationContext context1=new ClassPathXmlApplicationContext("spring.xml"); HelloService helloService1= (HelloService) context1.getBean("helloService"); helloService1.hello();
十,DI依赖注入
//创建一个类A
public class A {
public void str(){
System.out.println("我是A,被使用了");
}
}
//创建一个类B,B中依赖A对象
public class B {
//普通应该是 =new A(),在IOC容器中,new 的事情全部交给容器来
private A a;
//创建一个方法,方法需要使用A对象
public void saveA(){
a.str();
}
}
-
set注入(默认,常用)
//B中添加一个set方法 public class B { private A a; //为a设定一个set修改方法 public void setA(A a) { this.a = a; } public B(A a) { this.a = a; } }
<bean id="a" class="A"></bean> <bean id="b" class="B"> <!-- name:B中的A的实例对象名 ref:xml配置文件中A的配置id --> <property name="a" ref="a"></property> </bean>
-
构造器注入
//B中添加一个代参构造 public class B { private A a; //代参构造 public void setA(A a) { this.a = a; } public B(A a) { this.a = a; } }
<bean id="a" class="A"></bean> <bean id="b" class="B"> <constructor-arg ref="a" ></constructor-arg> </bean>
注入的选择:Bean通过构造器注入,之间彼此如果相互依赖对方导致bean无法正常实例化,导致死循环
使用开发项目中set方法注入首选
-
静态工厂注入
1. 就是将使用静态工厂获取到的bean对象id给到set注入中bean id属性中
-
实例化工厂注入
1. 将实例化工厂获取到的bean对象id 给到 实例化工厂注入中 bean ref属性中
-
p标签c标签
<!-- 在xml配置文件中添加 --> xmlns:p="http://www.springframework.org/schema/p" <!-- 例如 --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- set注入可以 --> <bean id="a" class="A"></bean> <bean id="b" class="B" p:a-ref="a" <!-- 如果还有其他基本类型属性的话,也可以这样设置 --> p:age="20" p:uname="sxt" > </bean>
<!-- 在xml配置文件中添加 --> xmlns:c="http://www.springframework.org/schema/c" <!-- 例如 --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- c构造器注入,如果参数有多个 --> <bean id="a" class="A"></bean> <bean id="b" class="B" c:_0-ref="a" c:_1="16" c:_2="zhangsan" > </bean>
-
集合注入
当类中有集合属性时,在需要给他们赋予初始值的时候可以
<!-- 集合注入 --> <bean id="dataService" class="com.shsxt.service.DataService"> <property name="list"> <list> <value>河南烩面</value> <value>南方臊子面</value> <value>油泼面</value> <value>方便面</value> </list> </property> <property name="set"> <set> <value>快乐小馒头</value> <value>北方馒头</value> <value>天津麻花</value> <value>新疆大饼</value> </set> </property> <property name="map"> <map> <entry> <key><value>河南</value></key> <value>云台山风景</value> </entry> <entry> <key><value>上海</value></key> <value>宝塔</value> </entry> <entry> <key><value>北京</value></key> <value>紫禁城</value> </entry> </map> </property> <property name="prop"> <props> <prop key="北京">北京尚学堂</prop> <prop key="上海">上海尚学堂</prop> <prop key="西安">西安尚学堂</prop> </props> </property> </bean>