Spring基礎1
Spring
簡介
Spring:春天---->給軟體行業帶來了春天
2002,首次推出了Spring框架的雛形:interface21框架
Spring框架即以interface21框架為基礎,經過重新設計,並不斷豐富其內涵,於2004年3月24日,釋出了1.0正式版
Spring理念:使現有的技術更加容易使用,本身是一個大雜燴,整合了現有的技術框架
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.9.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.9.RELEASE</version> </dependency>
官方文件:https://docs.spring.io/spring-framework/docs/5.2.9.RELEASE/spring-framework-reference/
優點
Spring是一個開源的免費的框架(容器)
Spring是一個輕量級的,非入侵式的框架
控制反轉(IOC),面向切面程式設計(AOP)
支援事務的處理,對框架整合的支援
總結:Spring就是一個輕量級的控制反轉(IOC)和麵向切面程式設計(AOP)的框架
IOC理論推導
UserDao介面
UserDaoImpl實現類
UserService業務介面
UserServiceImpl業務實現類
在之前的業務中,使用者的需求可能會影響我們原來的程式碼,我們需要根據使用者的需求去修改原始碼,如果程式程式碼量十分大,修改一次的成本代價十分昂貴
package com.company.dao;
public interface UserDao {
void getUser();
}
package com.company.dao;
public class UserDaoImpl implements UserDao{
@Override
public void getUser() {
System.out.println("預設獲取使用者的資料");
}
}
package com.company.dao; public class UserDaoMysqlImpl implements UserDao{ @Override public void getUser() { System.out.println("預設獲取Mysql的資料"); } }
package com.company.service;
public interface UserService {
void getUser();
}
package com.company.service;
import com.company.dao.UserDao;
public class UserServiceImpl implements UserService{
private UserDao userDao;
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
@Override
public void getUser() {
userDao.getUser();
}
}
import com.company.dao.UserDaoMysqlImpl;
import com.company.service.UserService;
import com.company.service.UserServiceImpl;
import org.junit.Test;
public class MyTest {
@Test
public void test1(){
UserService userService = new UserServiceImpl();
((UserServiceImpl) userService).setUserDao(new UserDaoMysqlImpl());
userService.getUser();
}
}
我們使用一個Set介面實現:
package com.company.service;
import com.company.dao.UserDao;
public class UserServiceImpl implements UserService{
private UserDao userDao;
//利用set進行動態實現值的注入
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
@Override
public void getUser() {
userDao.getUser();
}
}
- 之前,程式是主動建立物件,控制權在程式設計師手上
- 使用了set注入後,程式不再具有主動性,而是變成了被動的接受物件
這種思想,從本質上解決了問題,我們程式設計師不用再去管理物件的建立了,耦合性大大降低,可以更專注在業務的實現上,這是IOC的原型
IoC本質
採用XML方式配置Bean的時候,Bean的定義資訊是和實現分離的,而採用註解的方式可以把兩者合為一體,Bean的定義資訊直接以註解的形式定義在實現類中,從而達到了零配置的目的
控制反轉是一種通過描述(XML或註解)並通過第三方去生產的或獲取特定物件的方式,在Spring中實現控制反轉的是IoC容器,其實現方法是依賴注入(Dependency Injection,DI)
HelloString
pojo
package com.company.pojo;
public class Hello {
private String str;
public void setStr(String name) {
this.str = name;
}
public String getStr() {
return str;
}
@Override
public String toString() {
return "Hello{" +
"str='" + str + '\'' +
'}';
}
}
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">
<!--
value:具體的值,基本資料型別
ref:引用Spring容器中建立好的物件
-->
<!--使用Spring來建立物件,在Spring這些都稱為Bean-->
<bean id="hello" class="com.company.pojo.Hello">
<property name="str" value="Spring"/>
</bean>
</beans>
測試
import com.company.pojo.Hello;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@SuppressWarnings("all")
public class Mytest {
@Test
public void test(){
//獲取Spring的上下文物件
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//我們的物件現在都在Spring中的管理了,我們要使用,直接去裡面取出來就可以
Hello hello =(Hello) context.getBean("hello");
System.out.println(hello.toString());
}
}
IoC建立物件的方式
- 使用無參構造建立物件,預設
- 假設我們要使用有參構造建立物件
<!--第一種下標賦值-->
<bean id="user" class="com.company.pojo.User">
<constructor-arg index="0" value="ming"/>
</bean>
<!--第二種型別建立,不建議使用-->
<bean id="user" class="com.company.pojo.User">
<constructor-arg type="java.lang.String" value="gg"/>
</bean>
<!--第三種直接通過引數名賦值-->
<bean id="user" class="com.company.pojo.User">
<constructor-arg name="name" value="方法"/>
</bean>
總結:在配置檔案載入的時候,容器中管理的物件就已經初始化了,
Spring配置說明
別名
<alias name="user" alias="aaa"/>
如果添加了別名,兩個名字都能取出來
bean的配置
<!--
id:bean的唯一識別符號,也就是相當於我們學的物件名
class:bean物件所對應的全限定名:包名+型別
name:也是別名,而且name。可以同時取多個別名
-->
<bean id="user" class="com.company.pojo.User" name="user2 u2">
<constructor-arg name="name" value="方法"/>
</bean>
import
這個import,一般用於團隊開發使用,他可以將多個配置檔案,匯入合併為一個
<import resource="beans.xml"/> <!--建立xml的時候,主xml設定為beans而不是create applicationcontext-->
依賴注入
構造器注入
set方式注入
依賴注入:Set注入!
- 依賴:bean物件的建立依賴於容器
- 注入:bean物件中的所有屬性,由容器來注入
環境搭建:
-
複雜型別:
-
package com.company.pojo; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; public class Student { private String name; private Address address; private String[] books; private List<String> hobbys; private Map<String,String> card; private Set<String> games; private String wife; private Properties info; public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public String[] getBooks() { return books; } public void setBooks(String[] books) { this.books = books; } public List<String> getHobbys() { return hobbys; } public void setHobbys(List<String> hobbys) { this.hobbys = hobbys; } public Map<String, String> getCard() { return card; } public void setCard(Map<String, String> card) { this.card = card; } public Set<String> getGames() { return games; } public void setGames(Set<String> games) { this.games = games; } public String getWife() { return wife; } public void setWife(String wife) { this.wife = wife; } public Properties getInfo() { return info; } public void setInfo(Properties info) { this.info = info; } }
package com.company.pojo; public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
-
真實測試物件
拓展方式注入
<?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.company.pojo.Address"/>
<bean id="student" class="com.company.pojo.Student">
<!--普通值注入-->
<property name="name" value="ming"/>
<!--bean注入 ref-->
<property name="address" ref="address"/>
<!--陣列注入-->
<property name="books">
<array>
<value>紅樓夢</value>
<value>西遊記</value>
<value>水滸傳</value>
<value>三國演義</value>
</array>
</property>
<!--list注入-->
<property name="hobbys">
<list>
<value>聽歌</value>
<value>敲程式碼</value>
<value>看電影</value>
</list>
</property>
<!--map注入-->
<property name="card">
<map>
<entry key="身份證" value="333"/>
<entry key="銀行卡" value="555"/>
<entry key="學生卡" value="xxx"/>
</map>
</property>
<!--set注入-->
<property name="games">
<set>
<value>lol</value>
<value>coc</value>
<value>bob</value>
</set>
</property>
<!--null注入-->
<property name="wife">
<null/>
</property>
<!--properties注入-->
<property name="info">
<props>
<prop key="學號">1771733</prop>
<prop key="性別">男</prop>
<prop key="姓名">明明</prop>
</props>
</property>
</bean>
</beans>
c命名和p名稱空間注入
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
<!--p名稱空間注入,可以直接注入屬性的值:property-->
<bean id="user" class="com.company.pojo.User" p:name="明明" p:age="18"/>
ApplicationContext context = new ClassPathXmlApplicationContext("userbean.xml");
User user = context.getBean("user", User.class);
System.out.println(user.toString());
<!--c名稱空間注入,通過構造器注入:constructor-arg-->
<bean id="user2" class="com.company.pojo.User" c:age="18" c:name="mingming"/>
bean的作用域
<bean id="user2" class="com.company.pojo.User" c:age="18" c:name="mingming" scope="singleton"/>
單例模式:預設是單例,但也可以顯示加上
原型模式:每次從容器中get的時候,都會產生一個新物件
其餘的request,session,application這些個只能在web開發中使用到