文章大綱 一、Spring介紹二、Spring的IoC實戰三、IoC常見註解總結四、項目源碼及參考資料下載五、參考文章 一、Spring介紹 1. 什麼是Spring Spring是分層的Java SE/EE應用 full-stack輕量級開源框架,以IoC(Inverse Of Control:反 ...
文章大綱
一、Spring介紹
二、Spring的IoC實戰
三、IoC常見註解總結
四、項目源碼及參考資料下載
五、參考文章
一、Spring介紹
1. 什麼是Spring
Spring是分層的Java SE/EE應用 full-stack輕量級開源框架,以IoC(Inverse Of Control:反轉控制)和AOP(Aspect Oriented Programming:面向切麵編程)為內核,提供了展現層Spring MVC和持久層Spring JDBC以及業務層事務管理等眾多的企業級應用技術,還能整合開源世界眾多著名的第三方框架和類庫,逐漸成為使用最多的Java EE企業應用開源框架。
2. Spring優勢
方便解耦,簡化開發
通過Spring提供的IoC容器,可以將對象間的依賴關係交由Spring進行控制,避免硬編碼所造成的過度程式耦合。用戶也不必再為單例模式類、屬性文件解析等這些很底層的需求編寫代碼,可以更專註於上層的應用。
AOP編程的支持
通過Spring的AOP功能,方便進行面向切麵的編程,許多不容易用傳統OOP(面向對象的程式設計)實現的功能可以通過AOP輕鬆應付。
聲明式事務的支持
可以將我們從單調煩悶的事務管理代碼中解脫出來,通過聲明式方式靈活的進行事務的管理,提高開發效率和質量。
方便程式的測試
可以用非容器依賴的編程方式進行幾乎所有的測試工作,測試不再是昂貴的操作,而是隨手可做的事情。
方便集成各種優秀框架
Spring可以降低各種框架的使用難度,提供了對各種優秀框架(Struts、Hibernate、Hessian、Quartz等)的直接支持。
降低JavaEE API的使用難度
Spring對JavaEE API(如JDBC、JavaMail、遠程調用等)進行了薄薄的封裝層,使這些API的使用難度大為降低。
3. spring的體繫結構
二、Spring的IOC實戰
控制反轉(Inversion of Control,縮寫為IoC),是面向對象編程中的一種設計原則,可以用來減低電腦代碼之間的耦合度。其中最常見的方式叫做依賴註入(Dependency Injection,簡稱DI),還有一種方式叫“依賴查找”(Dependency Lookup)。通過控制反轉,對象在被創建的時候,由一個調控系統內所有對象的外界實體將其所依賴的對象的引用傳遞給它。也可以說,依賴被註入到對象中。
IoC有兩種實現方式,一種是配置文件(bean管理)方式,具體包括使用類的無參數構造方法(重點)、使用靜態工廠創建、使用實例工廠創建。第二種是註解方式。
1. 創建項目
2. 添加jar包(實際開發中使用maven)
將jar包複製到以下文件夾中
設置依賴
具體方式可參考博客中地址:https://zyjustin9.iteye.com/blog/2172445
3. 配置文件(bean管理)方式實現
方式一:使用id配置方法--常用(重要)
創建測試類User.java
public class User {
public void add() {
System.out.println("add.......");
}
public void add(String haha)
{
System.out.println("add.."+haha);
}
}
src下創建配置文件myXml.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" >
<!--
本來在該配置文件中還有一個屬性name,其作用和id一樣,id屬性值不能包含特殊符號(比如@#),但是name屬性可以,不過name屬性是很早版本時候使用的,現在都被替換成id了
scope屬性,總共有以下的值,但是最主要用的是前兩個,後面兩個不用記得,在該配置文件中我們沒有寫scope屬性,預設使用的是singleton
singleton:預設值、單例的
prototype:多例的:
request:創建對象,把對象放在request域裡面
session:創建對象,把對象放在session域裡面
globalSession:創建對象,把對象放在globalSession域裡面
-->
<!-- 第一種方法:ioc的配置文件 id是類的標誌 class是對象類全路徑-->
<bean id="user" class="ioc1.User" scope="singleton"/>
</beans>
編寫測試代碼
/**
* 測試配置方式實現IOC三種方法
*
* @author 吳曉暢
*
*/
public class TestIoc {
@Test
public void testUser() {
//載入spring配置文件,根據內容創建對象
ApplicationContext context = new ClassPathXmlApplicationContext("myXml.xml");
//方法1 :使用id配置方法--常用
User user = (User) context.getBean("user");
System.out.println(user);
user.add("尼瑪");
}
}
運行結果如下:
方式二:靜態工廠(瞭解就好)
創建測試類User2.java
package ioc2;
public class User2 {
public void add() {
System.out.println("user2........");
}
}
創建測試工廠類User2Factory.java
package ioc2;
public class User2Factory {
public static User2 getUser2()
{
return new User2();
}
}
src下創建配置文件myXml.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" >
<!--
本來在該配置文件中還有一個屬性name,其作用和id一樣,id屬性值不能包含特殊符號(比如@#),但是name屬性可以,不過name屬性是很早版本時候使用的,現在都被替換成id了
scope屬性,總共有以下的值,但是最主要用的是前兩個,後面兩個不用記得,在該配置文件中我們沒有寫scope屬性,預設使用的是singleton
singleton:預設值、單例的
prototype:多例的:
request:創建對象,把對象放在request域裡面
session:創建對象,把對象放在session域裡面
globalSession:創建對象,把對象放在globalSession域裡面
-->
<!-- 第二種方法:使用靜態工廠創建對象 -->
<bean id="user2" class="ioc2.User2Factory" factory-method="getUser2"/>
</beans>
測試代碼如下:
package introduction;
import ioc1.User;
import ioc2.User2;
import ioc3.User3;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 測試配置方式實現IOC三種方法
*
* @author 吳曉暢
*
*/
public class TestIoc {
@Test
public void testUser() {
//載入spring配置文件,根據內容創建對象
ApplicationContext context = new ClassPathXmlApplicationContext("myXml.xml");
//方法2:使用靜態工廠方法--瞭解就好
User2 user2 = (User2) context.getBean("user2");
System.out.println(user2);
}
}
運行結果如下:
方式三:實例工廠(瞭解就好)
創建測試類User3.java
package ioc3;
public class User3 {
public void add() {
System.out.println("user3........");
}
}
創建測試工廠類User3Factory.java
package ioc3;
public class User3Factory {
//普通方法,返回User3對象
public User3 getUser3()
{
return new User3();
}
}
src下創建配置文件myXml.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" >
<!--
本來在該配置文件中還有一個屬性name,其作用和id一樣,id屬性值不能包含特殊符號(比如@#),但是name屬性可以,不過name屬性是很早版本時候使用的,現在都被替換成id了
scope屬性,總共有以下的值,但是最主要用的是前兩個,後面兩個不用記得,在該配置文件中我們沒有寫scope屬性,預設使用的是singleton
singleton:預設值、單例的
prototype:多例的:
request:創建對象,把對象放在request域裡面
session:創建對象,把對象放在session域裡面
globalSession:創建對象,把對象放在globalSession域裡面
-->
<!-- 第三種方法:使用實例工廠創建對象 -->
<!-- 創建工廠類的對象 -->
<bean id="User3Factory" class="ioc3.User3Factory"></bean>
<bean id="user3" factory-bean="User3Factory" factory-method="getUser3"></bean>
</beans>
測試代碼如下:
package introduction;
import ioc3.User3;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 測試配置方式實現IOC三種方法
*
* @author 吳曉暢
*
*/
public class TestIoc {
@Test
public void testUser() {
//載入spring配置文件,根據內容創建對象
ApplicationContext context = new ClassPathXmlApplicationContext("myXml.xml");
//方法3:使用實例工廠創建對象--瞭解就好
User3 user3 = (User3) context.getBean("user3");
System.out.println(user3);
}
}
運行結果如下:
4. 註解方式實現
方式一:實現對象創建
創建測試類:UserBean1.java
/**
* 採用註解方式完成ioc
*
* @author 吳曉暢
*
*/
//目前spring有四個註解,功能都是一樣的,都是創建對象用的
//@Component @Controller @Service @Repository
@Component(value="userBean1")//這個相當於<bean id="user" class=""/>
public class UserBean1 {
public void add() {
System.out.println("UserBean1....add");
}
}
src下創建配置文件bean.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"
xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here -->
<!--
開啟註解掃描 base-package寫的包名 如果類在多個包裡面,那麼寫的方式如下
ioc_bean1,ioc_bean2,ioc_bean3...
或者採用cn 這樣表示載入cn開頭的所有包 cn.ioc則表示載入 cn.ioc開頭的所有包
-->
<!-- 到包裡面掃描類、方法、屬性上面註解 -->
<context:component-scan base-package="ioc_bean1"></context:component-scan>
<!-- 只掃描屬性上面的註解 -->
<!--<context:annotation-config></context:annotation-config> -->
</beans>
測試代碼如下
package introduction;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import ioc_bean1.UserBean1;
import ioc_bean1.UserService;;
/**
* 測試bean方式使用IOC
*
* @author 吳曉暢
*
*/
public class TestBean {
@Test
public void testUser() {
//載入spring配置文件,根據內容創建對象
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
//測試bean配置方式創建對象
UserBean1 userBean1 = (UserBean1) context.getBean("userBean1");
System.out.println(userBean1);
userBean1.add();
}
}
運行結果如下
方式二:bean配置方式註入對象屬性
創建測試類:UserDao.java
import org.springframework.stereotype.Component;
//這一步相當於創建了UserDao對象
@Component(value="userDao")
public class UserDao {
public void add() {
System.out.println("UserDao....add");
}
}
編寫測試類UserService.java
package ioc_bean1;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
//@Service(value="userService")等同於@Service("userService")
//這一步相當於創建了UserService對象
@Service(value="userService")
public class UserService {
//得到UserDao對象 使用註解方式時候不需要使用set方法,直接到UserDao對象上面使用註解,完成對象註入
//即@Autowired用於註入屬性
@Autowired
private UserDao userDao;
//這種方式與上面方式能達到同樣效果 常用的是下麵這種
//name的值要與UserDao的註解的value一致
// @Resource(name="userDao")
// private UserDao userDao;
public void add() {
System.out.println("UserService...add....");
userDao.add();
}
}
src下配置方式與方式一一致
測試代碼如下:
package introduction;
import ioc_bean1.UserBean1;
import ioc_bean1.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
;
/**
* 測試bean方式使用IOC
*
* @author 吳曉暢
*
*/
public class TestBean {
@Test
public void testUser() {
//載入spring配置文件,根據內容創建對象
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
//測試bean配置方式註入對象屬性
UserService userService = (UserService) context.getBean("userService");
userService.add();
}
}
運行結果如下
溫馨提示:
上面註解方式需要在使用類上面加上@Component(value="userDao"),在對象變數上使用@Autowired才能實現。
方式三:配置文件與註解方式混合使用
創建測試類BookDao.java
package ioc_bean2;
public class BookDao {
public void book() {
System.out.println("BookDao....book");
}
}
創建測試類OrderDao.java
package ioc_bean2;
public class OrderDao {
public void buy() {
System.out.println("OrderDao....buy");
}
}
創建測試服務BookService.java,在該服務中通過註解方式註入對象屬性
package ioc_bean2;
import javax.annotation.Resource;
public class BookService {
//得到BookDao和OrderDao的對象
@Resource(name="bookDao")
private BookDao bookDao;
@Resource(name="orderDao")
private OrderDao orderDao;
public void add() {
System.out.println("service");
bookDao.book();
orderDao.buy();
}
}
src下配置文件如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here -->
<!--
開啟註解掃描 base-package寫的包名 如果類在多個包裡面,那麼寫的方式如下
ioc_bean1,ioc_bean2,ioc_bean3...
或者採用cn 這樣表示載入cn開頭的所有包 cn.ioc則表示載入 cn.ioc開頭的所有包
-->
<!-- 到包裡面掃描類、方法、屬性上面註解 -->
<context:component-scan base-package="ioc_bean2"></context:component-scan>
<!-- 配置對象 -->
<bean id="bookService" class="ioc_bean2.BookService"></bean>
<bean id="bookDao" class="ioc_bean2.BookDao"></bean>
<bean id="orderDao" class="ioc_bean2.OrderDao"></bean>
</beans>
測試代碼如下
package ioc_bean2;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import ioc1.User;
import ioc2.User2;
import ioc3.User3;
public class TestMixBean {
@Test
public void testService() {
//載入spring配置文件,根據內容創建對象
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
BookService bookService = (BookService) context.getBean("bookService");
bookService.add();
}
}
運行結果如下
方式四:帶參數的屬性註入
創建數組、集合、properties屬性註入測試類Person.java
package property;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* 測試數組、集合、properties屬性註入
*
* @author 吳曉暢
*
*/
public class Person {
private String pName;
private String[] arrs;
private List<String> list;
private Map<String, String> map;
private Properties properties;
public void setpName(String pName) {
this.pName = pName;
}
public void setArrs(String[] arrs) {
this.arrs = arrs;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public void test1() {
System.out.println("pName--"+pName);
System.out.println("arrs--"+arrs);
System.out.println("list--"+list);
System.out.println("map--"+map);
System.out.println("properties--"+properties);
}
}
創建構造方法註入屬性測試類PropertyDemo1.java
package property;
/**
* 通過構造方法註入屬性
*
* @author 吳曉暢
*
*/
public class PropertyDemo1 {
private String userName;
public PropertyDemo1(String userName) {
this.userName = userName;
}
public void test1() {
System.out.println("demo1......"+userName);
}
}
創建set方法註入屬性測試類PropertyDemo2.java
package property;
/**
* 通過set方法註入屬性
*
* @author 吳曉暢
*
*/
public class PropertyDemo2 {
private String bookName;
//set方法 該方法一定要符合set/get方法命名規則
public void setBookName(String bookName) {
this.bookName = bookName;
}
public void demoBookName()
{
System.out.println("book..."+bookName);
}
}
對象屬性註入測試類UserDao.java
package property;
/**
* 對象屬性註入
*
* @author 吳曉暢
*
*/
public class UserDao {
public void add() {
System.out.println("UserDao.....dao");
}
}
對象屬性註入測試類UserService.java
package property;
/**
* 對象屬性註入
*
* @author 吳曉暢
*
*/
public class UserService {
//定義UserDao屬性
private UserDao dao;
//定義set方法
public void setDao(UserDao dao) {
this.dao = dao;
}
public void add() {
System.out.println("UserService...service");
//使用dao對象
dao.add();
}
}
src下配置文件myXml.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" >
<!--
本來在該配置文件中還有一個屬性name,其作用和id一樣,id屬性值不能包含特殊符號(比如@#),但是name屬性可以,不過name屬性是很早版本時候使用的,現在都被替換成id了
scope屬性,總共有以下的值,但是最主要用的是前兩個,後面兩個不用記得,在該配置文件中我們沒有寫scope屬性,預設使用的是singleton
singleton:預設值、單例的
prototype:多例的:
request:創建對象,把對象放在request域裡面
session:創建對象,把對象放在session域裡面
globalSession:創建對象,把對象放在globalSession域裡面
-->
<!-- 使用有參數構造註入屬性 -->
<bean class="property.PropertyDemo1" id="demo">
<!-- 表示給userName屬性註入value為小王的值 -->
<constructor-arg value="小王" name="userName"> </constructor-arg>
</bean>
<!-- 使用set方法註入屬性 -->
<!--這一步相當於創建了 property.PropertyDemo2類的對象-->
<bean class="property.PropertyDemo2" id="demo2">
<!-- 表示給userName屬性註入value為小王的值 -->
<property value="易筋經" name="bookName"> </property>
</bean>
<!-- 註入對象類型的屬性 -->
<!-- 配置UserService和UserDao的對象 -->
<bean id="userDao" class="property.UserDao"></bean>
<bean id="userService" class="property.UserService">
<!-- 註入dao對象 現在不要寫value屬性,因為上面是字元串,現在是對象,使用ref屬性,dao配置bean標簽中的id值-->
<property name="dao" ref="userDao"></property>
</bean>
<!-- 註入複雜類型屬性-》包括數組、集合等 -->
<bean id="person" class="property.Person">
<!-- 數組 -->
<property name="arrs">
<list>
<value>小王</value>
<value>小馬</value>
<value>小宋</value>
</list>
</property>
<!-- list集合 -->
<property name="list">
<list>
<value>小奧</value>
<value>小金</value>
<value>小普</value>
</list>
</property>
<!-- map集合 -->
<property name="map">
<map>
<entry key="aa" value="Lucy"></entry>
<entry key="bb" value="Mary"></entry>
<entry key="cc" value="Tom"></entry>
</map>
</property>
<!-- properties -->
<property name="properties">
<props>
<prop key="driverclass">com.mysql.jdbc.Driver</prop>
<prop key="username">root</prop>
</props>
</property>
</bean>
</beans>
測試代碼如下
package property;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 測試屬性註入
*
* @author 吳曉暢
*
*/
public class TestIoc {
@Test
public void textUser() {
//載入spring配置文件,根據內容創建對象
ApplicationContext context = new ClassPathXmlApplicationContext("myXml.xml");
//測試構造註入屬性的方法
//得到配置創建的對象
PropertyDemo1 demo1 = (PropertyDemo1)context.getBean("demo");
demo1.test1();
//測試set方法註入屬性值
PropertyDemo2 demo2 = (PropertyDemo2)context.getBean("demo2");
demo2.demoBookName();
//測試使用set方法註入對象屬性
UserService userService = (UserService) context.getBean("userService");
userService.add();
//使用set方法註入複雜屬性對象
Person person = (Person) context.getBean("person");
person.test1();
}
}
運行結果如下
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
demo1......小王
book...易筋經
UserService...service
UserDao.....dao
pName--null
arrs--[Ljava.lang.String;@28ac3dc3
list--[小奧, 小金, 小普]
map--{aa=Lucy, bb=Mary, cc=Tom}
properties--{driverclass=com.mysql.jdbc.Driver, username=root}
Process finished with exit code 0
三、IoC常見註解總結
- 創建對象(相當於:<bean id="" class="">)
(1)@Component
作用:把資源讓spring來管理。相當於在xml中配置一個bean。
屬性:value:指定bean的id。如果不指定value屬性,預設bean的id是當前類的類名。首字母小寫。
(2)@Controller @Service @Repository
他們三個註解都是針對一個的衍生註解,他們的作用及屬性都是一模一樣的。
他們只不過是提供了更加明確的語義化。
@Controller:一般用於表現層的註解。
@Service:一般用於業務層的註解。
@Repository:一般用於持久層的註解。
細節:如果註解中有且只有一個屬性要賦值時,且名稱是value,value在賦值是可以不寫。
- 用於註入數據(相當於:<property name="" ref=""> <property name="" value="">)
(1)@Autowired
作用:自動按照類型註入。當使用註解註入屬性時,set方法可以省略。它只能註入其他bean類型。當有多個類型匹配時,使用要註入的對象變數名稱作為bean的id,在spring容器查找,找到了也可以註入成功。找不到就報錯。
(2)@Resource
作用:直接按照Bean的id註入。它也只能註入其他bean類型。
屬性:name:指定bean的id。
(3)@Value
作用:註入基本數據類型和String類型數據的
屬性:value:用於指定值
四、項目源碼及參考資料下載
鏈接:https://pan.baidu.com/s/1RDBXQcBchtA9i-bg8Z1r4Q
提取碼:io8n
五、參考文章
http://yun.itheima.com/course/215.html?1804lckj