1幌衣、Spring
1.1 簡介
- Spring:春天---->給軟件行業(yè)帶來了春天矾削!
- 2002,首次推出了Spring框架的雛形:interface21框架豁护!
- Spring框架即以interface21框架為基礎哼凯,經過重新設計,并不斷豐富內涵楚里,于2004年3月24日断部,發(fā)布了1.0正式版。
- Rod Johnson班缎,Spring Framework創(chuàng)始人蝴光,著名作者。很難想象其學歷达址,真的讓好多人大吃一驚蔑祟,他是悉尼大學的博士,然而他的專業(yè)不是計算機沉唠,而是音樂學疆虚。
- spring理念:使現有的技術更加容易使用,本身是一個大雜燴满葛,整合了現有的技術框架装蓬。
- SSH:Struct2+Spring+Hibernate!
- SSM:SpringMVC+Spring+Mybatis!
?
官網:https://spring.io/projects/spring-framework#overview
官方下載地址:https://repo.spring.io/release/org/springframework/spring/
Github:https://github.com/spring-projects/spring-framework
Maven倉庫:導入webmvc包會自動導入相關依賴;jdbc用于和Mybatis整合纱扭。
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
1.2 優(yōu)點
Spring是一個開源的免費的框架(容器)牍帚!
Spring是一個輕量級的、非入侵式的框架乳蛾!
控制反轉(IOC)暗赶、面向切面編程(AOP)!
-
支持事務的處理肃叶,對框架整合的支持蹂随!
==總結一句話:Spring就是一個輕量級的控制反轉(IOC)和面向切面編程的框架!==
1.3 組成
1.4 拓展
在Spring的官網有這個介紹:現代化的java開發(fā)因惭!說白了就是基于Spring的開發(fā)岳锁!
- Spring Boot
- 一個快速開發(fā)的腳手架。
- 基于Spring Boot可以快速的開發(fā)單個微服務蹦魔。
- 約定大于配置激率!
- Spring Cloud
- SpringCloud是基于SpringBoot實現的咳燕。
因為現在大多數公司都在使用SpringBoot進行快速開發(fā),學習SpringBoot的前提乒躺,需要完全掌握Spring以及SpringMVC招盲!承上啟下的作用。
弊端:發(fā)展了太久之后嘉冒,違背了原來的理念曹货!配置十分繁瑣,人稱:“配置地獄”讳推。
2顶籽、 IOC理論推導
1.UserDao接口
2.UserDaoImpl實現類
3.UserService業(yè)務接口
4.UserServiceImpl業(yè)務實現類
在我們之前的業(yè)務中,用戶的需求可能會影響我們原來的代碼银觅,我們需要根據用戶的需求去修改源代碼!如果程序代碼量十分大蜕衡,修改一次的成本代價十分昂貴!
我們使用一個Set接口實現设拟,已經發(fā)生了革命性的變化!
private UserDao userDao;
//利用set進行動態(tài)實現值的注入久脯!
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
- 之前纳胧,程序是主動創(chuàng)建對象!控制權在程序員手上帘撰!
- 使用了set注入后跑慕,程序不再具有主動性,而是變成了被動的接收對象摧找!
這種思想核行,從本質上解決了問題,我們程序員不用再去管理對象的創(chuàng)建了蹬耘。系統(tǒng)的耦合性大大降低芝雪,可以更加專注在業(yè)務的實現上。這是IOC的原型综苔!
IOC本質
控制反轉IOC(Inversion of Control)惩系,是一種設計思想,DI(依賴注入)是實現IOC的一種方法如筛,也有人認為DI是IoC的另一種說法堡牡。沒有IoC的程序中,我們使用面向對象編程杨刨,對象的創(chuàng)建與對象間的依賴關系完全硬編碼在程序中晤柄,對象的創(chuàng)建由程序自己控制,控制反轉后將對象的創(chuàng)建轉移給第三方妖胀,個人認為所謂控制反轉就是:獲得依賴對象的方式反轉了芥颈。
采用XML方式配置Bean的時候惠勒,Bean的定義信息是和實現分離的,而采用注解的方式可以把兩者合為一體浇借,Bean的定義信息直接以注解的形式定義在實現類中捉撮,從而達到了零配置的目的。
控制反轉是一種通過描述(XML或注解)并通過第三方去生產或獲取特定對象的方式妇垢。在Spring中實現控制反轉的是IoC容器巾遭,其實現方式是依賴注入(Dependency Injection,DI)。
3闯估、 Hello Spring
beans.xml官網配置文件:
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
bean對象添加:
<bean id="mysqlImpl" class="com.kuang.dao.UserDaoMysqlImpl"></bean>
<bean id="oracleImpl" class="com.kuang.dao.UserDaoOracleImpl"></bean>
<bean id="UserServiceImpl" class="com.kuang.service.UserServiceImpl">
<!--
ref:引用Spring容器中已經創(chuàng)建好的對象
value:具體的值灼舍,基本數據類型
-->
<property name="userDao" ref="mysqlImpl"></property>
</bean>
Test方法:
//解析beans.xml文件,生成管理相應的Bean對象
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//
Hello hello = (Hello) context.getBean("hello");
System.out.println(hello.toString());
思考問題涨薪?
-
Hello對象是誰創(chuàng)建的骑素?
hello對象是由Spring創(chuàng)建的。
-
Hello對象的屬性是怎么設置的刚夺?
hello對象的屬性是由Spring容器設置的献丑。
這個過程就叫做控制反轉:
控制:誰來控制對象的創(chuàng)建,傳統(tǒng)應用程序的對象是由程序本身控制創(chuàng)建的侠姑,使用Spring后创橄,對象是由Spring來創(chuàng)建的。
反轉:程序本身不創(chuàng)建對象莽红,而變成被動的接收對象妥畏。
依賴注入:就是利用set方法來進行注入。
IoC是一種編程思想安吁,由主動的編程編程被動的接收醉蚁。
可以通過new ClassPathXmlApplicationContext去瀏覽一下底層源碼。
OK鬼店,到了現在网棍,我們徹底不用在程序中去改動了,要實現不同的操作妇智,只需要在xml配置文件中進行修改确沸,所謂的IoC俘陷,一句話搞定:對象由Spring來創(chuàng)建,管理桨菜,裝配!
IDEA快捷創(chuàng)建beans.xml文件,自動導入spring配置信息:
4倒得、 IoC創(chuàng)建對象的方式
- 使用無參構造創(chuàng)建對象,默認方式霞掺!
<bean id="adress" class="com.domain.Address">
<property name="address" value="長春"/>
</bean>
-
假設我們要使用有參構造創(chuàng)建對象辅鲸。
1.下標賦值凌唬。
<!--第一種沼溜,下標賦值!--> <bean id="user" class="com.kuang.pojo.User"> <constructor-arg index="0" value="憨批" /> </bean>
2.類型賦值骗灶。
<!--第二種,通過類型創(chuàng)建耙旦,不建議使用,重復類型難以分辨--> <bean id="user" class="com.kuang.pojo.User"> <constructor-arg type="java.lang.String" value="大憨批" /> </bean>
3.參數名賦值锉罐。
<!--第三種绕娘,直接通過參數名來設置--> <bean id="user" class="com.kuang.pojo.User"> <constructor-arg name="name" value="臭憨批" /> </bean>
總結:在配置文件加載的時候,容器中管理的對象就已經初始化了业舍!
5升酣、 Spring配置
5.1 別名
<!--別名,如果添加了別名下面,我們也可以使用別名獲取到-->
<alias name="user" alias="userNew"></alias>
5.2 Bean的配置
<!--
id:bean的唯一標識符绩聘,相當于我們學的對象名;
class:bean對象所對應的全限定名:包名+類名凿菩;
name:也是別名衅谷,可以同時取多個別名,逗號分割
-->
<bean id="userT" class="com.kuang.pojo.UserT" name="user2,u2">
</bean>
5.3 import
這個import,一般用于團隊開發(fā)使用在验,他可以將多個配置文件堵未,導入合并為一個腋舌。
假設,現在項目中有多個人開發(fā)块饺,這三個人負責不同的類開發(fā)拙徽,不同的類需要注冊在不同的bean中,我們可以利用import將所有人的beans.xml合并為一個總的膘怕!
- 張三
- 李四
- 王五
- applicationContext.xml
<import resource="beans.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>
使用的時候岛心,直接使用總的配置就可以了。
6忘古、 依賴注入
6.1 構造器注入
之前已經介紹過。
6.2 Set方式注入【重點】
- 依賴注入:Set注入送朱!
- 依賴:bean對象的創(chuàng)建依賴于容器干旁!
- 注入:bean對象中的所有屬性,由容器來注入回怜!
【環(huán)境搭建】
-
復雜類型
public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
-
真實測試對象
public class Student { private String name; private Address address; private String[] books; private List<String> hobbies; private Map<String,String> card; private Set<String> games; private String wife; private Properties info; }
-
beans.xml
<?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="student" class="com.kuang.pojo.Student"> <!--第一種玉雾,普通值注入--> <property name="name" value="憨批"/> </bean> </beans>
-
測試類
public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student = (Student) context.getBean("student"); System.out.println(student.getName()); } }
-
==完善注入:==
<?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="address" class="com.kuang.pojo.Address"/>
<bean id="student" class="com.kuang.pojo.Student">
<!--第一種轻要,普通值注入,value-->
<property name="name" value="憨批"/>
<!--第二種赢底,Bean注入,ref-->
<property name="address" ref="address"/>
<!--數組注入-->
<property name="books">
<array>
<value>紅樓夢</value>
<value>西游記</value>
<value>水滸傳</value>
<value>三國演義</value>
</array>
</property>
<!--List注入-->
<property name="hobbies">
<list>
<value>聽歌</value>
<value>敲代碼</value>
<value>看電影</value>
</list>
</property>
<!--Map-->
<property name="card">
<map>
<entry key="身份證" value="1555555555"/>
<entry key="銀行卡" value="5555555555"/>
</map>
</property>
<!--Set-->
<property name="games">
<set>
<value>lol</value>
<value>wow</value>
</set>
</property>
<!--null-->
<property name="wife">
<null/>
</property>
<!--Properties-->
<property name="info">
<props>
<prop key="driver">com.mysql.jdbc.Driver</prop>
<prop key="url">jdbc:mysql://localhost:3306/news</prop>
<prop key="root">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
</beans>
6.3 拓展方式注入
我們可以使用c和p命令空間進行注入:
使用:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
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">
<!--p命名空間注入,可以直接注入屬性的值:property-->
<bean id="user" class="com.kuang.pojo.User" p:name="憨批" p:age="18"/>
<!--c命名空間注入庞溜,通過構造器注入:construct-args-->
<bean id="user2" class="com.kuang.pojo.User" c:age="18" c:name="憨批"/>
</beans>
測試:
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("userBeans.xml");
User user = context.getBean("user2", User.class);
System.out.println(user);
}
注意點:p和c命名空間不能直接使用碑定,需要導入xml約束!
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
6.4 bean的作用域
-
單例模式 Singleton(Spring默認機制):get到的都是同一個對象漫试!
<bean id="user2" class="com.kuang.pojo.User" c:age="18" c:name="憨批" scope="singleton"/>
-
原型模式 prototype:每次從容器中get的時候碘赖,都會產生一個新的對象!
<bean id="user2" class="com.kuang.pojo.User" c:age="18" c:name="憨批" scope="prototype"/>
其余的request播掷、session撼班、application、這些個只能在web開發(fā)中使用件炉。
7矮湘、 Bean的自動裝配
- 自動裝配是Spring滿足bean依賴的一種方式!
- Spring會在上下文中自動尋找板祝,并自動給bean裝配屬性走净!
在Spring中有三種裝配的方式:
- 在xml中顯式配置;
<bean id="cat" class="com.domain.Cat"/>
<bean id="dog" class="com.domain.Dog"/>
<bean id="person" class="com.domain.Person" >
<property name="name" value="于松江"/>
<property name="dog" ref="dog"/>
<property name="cat" ref="cat"/>
</bean>
- 隱式的自動裝配bean(抽取公共)橘洞;
- 在java中顯式配置说搅;
7.1 測試
環(huán)境搭建:一個人有兩個寵物!
7.2 ByName自動裝配
byName:會自動在容器上下文中查找和自己對象set方法后面的值對應的beanid适肠!
<bean id="people" class="com.kuang.pojo.People" autowire="byName">
<property name="name" value="憨批"/>
</bean>
7.3 ByType自動裝配
byType:會自動在容器上下文中查找,和自己對象屬性類型相同的bean敦跌!必須保證類型全局唯一
<bean id="people" class="com.kuang.pojo.People" autowire="byType">
<property name="name" value="憨批"/>
</bean>
小結:
- byName的時候逛揩,需要保證所有bean的id唯一,并且這個bean需要和自動注入的屬性的set方法的值一致惧笛!
- byType的時候逞泄,需要保證所有bean的class唯一,并且這個bean需要和自動注入的屬性的類型一致L堪谩(不能有兩個同種類型的變量)