介紹
Spring框架是個(gè)輕量級(jí)的Java EE框架。所謂輕量級(jí),是指不依賴(lài)于容器就能運(yùn)行的。Struts、Hibernate也是輕量級(jí)的。
輕量級(jí)框架是相對(duì)于重量級(jí)框架而言的,重量級(jí)框架必須依賴(lài)特定的容器,例如EJB框架就必須運(yùn)行在Glassfish、JBoss等支持EJB的容器中,而不能運(yùn)行在Tomcat中?!禞ava Web整合開(kāi)發(fā) 王者歸來(lái)》
Spring以IoC、AOP為主要思想,其中IoC,Inversion of Control 指控制反轉(zhuǎn)或反向控制。在Spring框架中我們通過(guò)配置創(chuàng)建類(lèi)對(duì)象,由Spring在運(yùn)行階段實(shí)例化、組裝對(duì)象。AOP,Aspect Oriented Programming,面向切面編程,其思想是在執(zhí)行某些代碼前執(zhí)行另外的代碼,使程序更靈活、擴(kuò)展性更好,可以隨便地添加、刪除某些功能。Servlet中的Filter便是一種AOP思想的實(shí)現(xiàn)。
Spring同時(shí)也是一個(gè)“一站式”框架,即Spring在JavaEE的三層架構(gòu)[表現(xiàn)層(Web層)、業(yè)務(wù)邏輯層(Service層)、數(shù)據(jù)訪(fǎng)問(wèn)層(DAO層)]中,每一層均提供了不同的解決技術(shù)。如下:
表現(xiàn)層(Web層):Spring MVC
業(yè)務(wù)邏輯層(Service層):Spring的IoC
數(shù)據(jù)訪(fǎng)問(wèn)層(DAO層):Spring的jdbcTemplate
Spring中的IoC操作
將對(duì)象的創(chuàng)建交由Spring框架進(jìn)行管理。
IoC操作分為:IoC配置文件方式和IoC的注解方式。
IoC入門(mén)案例
(1)導(dǎo)入Spring框架中的相關(guān)jar包,這里只導(dǎo)入Spring的Core模塊下的jar包(Core模塊是框架的核心類(lèi)庫(kù)),以及 支持日志輸出的 commons-logging 和 log4j 的jar包;
(2)創(chuàng)建一個(gè)普通的Java類(lèi),并在該類(lèi)中創(chuàng)建方法,如下:
User.java
package com.wm103.ioc;
public?class?User?{
public?void?add()?{
System.out.println("add...");
}
}
(3)創(chuàng)建Spring的配置文件,進(jìn)行Bean的配置?
Spring的核心配置文件名稱(chēng)和位置不是固定的。但官方件建議將該核心配置文件放在src目錄下,且命名為 applicationContext.xml。?
這里為了方便,將核心配置文件放在src目錄下,并命名為 bean1.xml,內(nèi)容如下:
?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">
(4)編寫(xiě)測(cè)試類(lèi)進(jìn)行測(cè)試,通過(guò)配置文件創(chuàng)建類(lèi)對(duì)象?
TestIoC.java
package?com.wm103.ioc;
import?org.junit.Test;
import?org.springframework.context.ApplicationContext;
import?org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Created by DreamBoy on 2017/5/31.
*/
public?class?TestIoC?{
@Test
public?void?testUser()?{
// 1. 加載Spring配置文件,根據(jù)創(chuàng)建對(duì)象
ApplicationContext context =?new?ClassPathXmlApplicationContext("bean1.xml");
// 2. 得到配置創(chuàng)建的對(duì)象
User user = (User) context.getBean("user");
System.out.println(user);
user.add();
}
}
Spring的bean管理(配置文件)
Bean實(shí)例化的方式
在Spring中通過(guò)配置文件創(chuàng)建對(duì)象。
Bean實(shí)例化三種方式實(shí)現(xiàn):
(1)使用類(lèi)的無(wú)參數(shù)構(gòu)造創(chuàng)建,如:
(2)使用靜態(tài)工廠(chǎng)創(chuàng)建?
如果一個(gè)Bean不能通過(guò)new直接實(shí)例化,而是通過(guò)工廠(chǎng)類(lèi)的某個(gè)靜態(tài)方法創(chuàng)建的,需要把的class屬性配置為工廠(chǎng)類(lèi)。如:
(3)使用實(shí)例工廠(chǎng)創(chuàng)建?
如果一個(gè)Bean不能通過(guò)new直接實(shí)例化,而是通過(guò)工廠(chǎng)類(lèi)的某個(gè)實(shí)例方法創(chuàng)建的,需要先配置工廠(chǎng)的標(biāo)簽,然后在需要?jiǎng)?chuàng)建的對(duì)象的bean標(biāo)簽的factory-bean屬性配置為工廠(chǎng)類(lèi)對(duì)象,factory-method屬性配置為產(chǎn)生實(shí)例的方法。如:
Bean標(biāo)簽的常用屬性
(1)id屬性:用于指定配置對(duì)象的名稱(chēng),不能包含特殊符號(hào)。
(2)class屬性:創(chuàng)建對(duì)象所在類(lèi)的全路徑。
(3)name屬性:功能同id屬性一致。但是在name屬性值中可以包含特殊符號(hào)。
(4)scope屬性
singleton:默認(rèn)值,單例
單例模式下,在程序下只有一個(gè)實(shí)例。非單態(tài)模式下,每次請(qǐng)求該Bean,都會(huì)生成一個(gè)新的對(duì)象。
prototype:多例
request:創(chuàng)建對(duì)象后將對(duì)象存放到request域
session:創(chuàng)建對(duì)象后將對(duì)象存放到session域
globalSession:創(chuàng)建對(duì)象后將對(duì)象存放到globalSession域
屬性注入
屬性注入指創(chuàng)建對(duì)象時(shí),向類(lèi)對(duì)象的屬性設(shè)置屬性值。
在Spring框架中支持set方法注入和有參構(gòu)造函數(shù)注入,即創(chuàng)建對(duì)象后通過(guò)set方法設(shè)置屬性或采用有參構(gòu)造函數(shù)創(chuàng)建對(duì)象并初始化屬性。
使用有參構(gòu)造函數(shù)注入屬性
案例:
Demo1.java 提供有參的構(gòu)造方法
package com.wm103.ioc;
public?class?Demo1?{
private?String demoName;
public?Demo1(String demoName)?{
this.demoName = demoName;
}
public?void?out()?{
System.out.println("This is Demo1.");
}
}
bean的配置:
創(chuàng)建Demo1對(duì)象進(jìn)行測(cè)試:
@Test
public?void?testDemo1()?
{
// 1. 加載Spring配置文件,根據(jù)創(chuàng)建對(duì)象
ApplicationContext context =?new?ClassPathXmlApplicationContext("bean1.xml");
// 2. 得到配置創(chuàng)建的對(duì)象
Demo1 demo1 = (Demo1) context.getBean("demo1");
System.out.println(demo1);
demo1.out();
}
使用set方法注入屬性
案例:
Demo2.java 提供屬性的set方法
package com.wm103.ioc;
public?class?Demo2?{
private?String demoName;
public?void?setDemoName(String demoName)?{
this.demoName = demoName;
}
public?void?out()?{
System.out.println("This is Demo2.");
}
}
bean的配置:
創(chuàng)建Demo2對(duì)象進(jìn)行測(cè)試:
@Test
public?void?testDemo2()?
{
// 1. 加載Spring配置文件,根據(jù)創(chuàng)建對(duì)象
ApplicationContext context =?new?ClassPathXmlApplicationContext("bean1.xml");
// 2. 得到配置創(chuàng)建的對(duì)象
Demo2 demo2 = (Demo2) context.getBean("demo2");
System.out.println(demo2);
demo2.out();
}
注入對(duì)象類(lèi)型屬性
以三層架構(gòu)中的service層和dao層為例,為了讓service層使用dao層的類(lèi)創(chuàng)建的對(duì)象,需要將dao對(duì)象注入到service層類(lèi)中。具體實(shí)現(xiàn)過(guò)程中如下:
(1)創(chuàng)建service類(lèi)、dao層接口、dao類(lèi),如下:
UserService.java
package com.wm103.ioc;
public?class?UserService?{
private?UserDao userDao;?// 聲明為接口類(lèi)型,降低service層與dao層的耦合度,不依賴(lài)于dao層的具體實(shí)現(xiàn)
public?void?setUserDao(UserDao userDao)?{
this.userDao = userDao;
}
public?void?add()?{
System.out.println("service add...");
this.userDao.add();
}
}
UserDao.java
package com.wm103.ioc;
/**
* 暴露給service層的接口
* Created by DreamBoy on 2017/5/31.
*/
public?interface?UserDao?{
void?add();
}
UserDaoImpl.java
package?com.wm103.ioc;
/**
* 接口的具體實(shí)現(xiàn)
* Created by DreamBoy on 2017/5/31.
*/
public?class?UserDaoImpl?implements?UserDao?{
@Override
public?void?add()?{
System.out.println("dao add...");
}
}
(2)在配置文件中注入關(guān)系,如下:
注入dao對(duì)象
name屬性值為:service中的某一屬性名稱(chēng)
ref屬性值為:被引用的對(duì)象對(duì)應(yīng)的bean標(biāo)簽的id屬性值
-->
(3)創(chuàng)建測(cè)試方法進(jìn)行測(cè)試,如下:
@Test
public?void?testUserService()?
{
ApplicationContext context =?new?ClassPathXmlApplicationContext("bean1.xml");
UserService userService = (UserService) context.getBean("userService");
System.out.println(userService);
userService.add();
}
p名稱(chēng)空間注入屬性
之前提到了一種set方法的屬性注入方式,這里將介紹另一種屬性注入的方式,名為 p名稱(chēng)空間注入。對(duì)比set方法的屬性注入方式,核心配置文件配置修改如下:
?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">
注入復(fù)雜類(lèi)型屬性
對(duì)象注入復(fù)雜類(lèi)型屬性,如數(shù)組、List、Map、Properties。
案例:
PropertyDemo.java
package com.wm103.ioc;
import?java.util.List;
import?java.util.Map;
import?java.util.Properties;
public?class?PropertyDemo?{
private?String[] arrs;
private?List?list;
private?Map?map;
private?Properties properties;
public?void?setArrs(String[] arrs)?{
this.arrs = arrs;
}
public?void?setList(List?list)?{
this.list?=?list;
}
public?void?setMap(Map?map)?{
this.map?=?map;
}
public?void?setProperties(Properties properties)?{
this.properties = properties;
}
public?String[] getArrs() {
return?arrs;
}
public?List getList() {
return?list;
}
public?Map getMap() {
return?map;
}
public?Properties?getProperties()?{
return?properties;
}
}
bean配置文件,內(nèi)容如下:
?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 1 of array
value 2 of array
value 3 of array
value 1 of list
value 2 of list
value 3 of list
root
123
IoC和DI的區(qū)別
IoC,控制反轉(zhuǎn),把對(duì)象的創(chuàng)建交給Spring進(jìn)行配置。
DI,依賴(lài)注入,向類(lèi)的屬性設(shè)置值。
IoC與DI的關(guān)系:依賴(lài)注入不能單獨(dú)存在,需要在IoC基礎(chǔ)之上完成操作。
Spring的bean管理(注解)
注解是代碼中特殊的標(biāo)記,使用注解可以完成特定的功能。注解可以使用在類(lèi)、方法或?qū)傩陨?,?xiě)法如:@注解名稱(chēng)(屬性名稱(chēng)=屬性值)。
Spring的bean管理注解方式,案例如下。
Spring注解開(kāi)發(fā)準(zhǔn)備
(1)導(dǎo)入jar包:
導(dǎo)入基本的jar包:commons-logging、log4j、spring-beans、spring-context、spring-core、spring-expression相關(guān)jar包。
導(dǎo)入AOP的jar包:spring-aopjar包。
(2)創(chuàng)建類(lèi)、方法?
User.java
package?com.wm103.anno;
import?org.springframework.stereotype.Component;
public?class?User?{
public?void?add()?{
System.out.println("User Add...");
}
}
(3)創(chuàng)建Spring配置文件,引入約束;并開(kāi)啟注解掃描?
bean1.xml
?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"
>
開(kāi)啟注解掃描
(1)到包中掃描類(lèi)、方法、屬性上是否有注解
-->
(2)掃描屬性上的注解
-->
注解創(chuàng)建對(duì)象
在創(chuàng)建對(duì)象的類(lèi)上面使用注解實(shí)現(xiàn),如:
@Component(value="user")
public?class?User?{
創(chuàng)建測(cè)試類(lèi) TestAnno.java和測(cè)試方法,如:
package?com.wm103.anno;
import?org.junit.Test;
import?org.springframework.context.ApplicationContext;
import?org.springframework.context.support.ClassPathXmlApplicationContext;
public?class?TestAnno?{
@Test
public?void?testUser()?{
ApplicationContext context =?new?ClassPathXmlApplicationContext("bean1.xml");
User user = (User) context.getBean("user");
System.out.println(user);
user.add();
}
}
除了上述提到的@Component注解外,Spring中還提供了@Component的3個(gè)衍生注解,其功能就目前來(lái)說(shuō)是一致的,均是為了創(chuàng)建對(duì)象。
@Controller :WEB層
@Servlet :業(yè)務(wù)層
@Repository :持久層
以單例或多實(shí)例方式創(chuàng)建對(duì)象,默認(rèn)為單例,多例對(duì)象設(shè)置注解如下:
@Component(value="user")
@Scope(value="prototype")
public class User {
注解注入屬性
案例:創(chuàng)建Service類(lèi)和Dao類(lèi),并在Service中注入Dao對(duì)象。如下:
(1)創(chuàng)建Dao和Service對(duì)象
UserDao.java
package?com.wm103.anno;
import?org.springframework.stereotype.Repository;
@Repository(value="userDao")
public?class?UserDao?{
public?void?add()?{
System.out.println("UserDao Add...");
}
}
UserService.java
package?com.wm103.anno;
import?org.springframework.stereotype.Service;
import?javax.annotation.Resource;
@Service(value="userService")
public?class?UserService?{
public?void?add()?{
System.out.println("UserService Add...");
}
}
(2)在Service類(lèi)中定義UserDao類(lèi)型的屬性,并使用注解完成對(duì)象的注入?
@Autowired
@Autowired
private?UserDao userDao;
或者?@Resource
@Resource(name="userDao")
private UserDao userDao;
其中該注解的name屬性值為注解創(chuàng)建Dao對(duì)象的value屬性的值。?
這兩種注解方式都不要為需要注入的屬性定義set方法。?
(3)創(chuàng)建測(cè)試方法
@Test
public?void?testUserService()?
{
ApplicationContext context =?new?ClassPathXmlApplicationContext("bean1.xml");
UserService userService = (UserService) context.getBean("userService");
System.out.println(userService);
userService.add();
}
注:配置文件和注解混合使用
1)創(chuàng)建對(duì)象的操作一般使用配置文件方式實(shí)現(xiàn);
2)注入屬性的操作一般使用注解方式實(shí)現(xiàn)。
在這里順便給大家推薦一個(gè)架構(gòu)交流群:617434785,里面會(huì)分享一些資深架構(gòu)師錄制的視頻錄像:有Spring,MyBatis,Netty源碼分析,高并發(fā)、高性能、分布式、微服務(wù)架構(gòu)的原理,JVM性能優(yōu)化這些成為架構(gòu)師必備的知識(shí)體系。還能領(lǐng)取免費(fèi)的學(xué)習(xí)資源。相信對(duì)于已經(jīng)工作和遇到技術(shù)瓶頸的碼友,在這個(gè)群里會(huì)有你需要的內(nèi)容