Spring簡介
Spring是一個輕量級、開源的框架,核心功能如下:
- IOC:控制反轉,對象額創建不是通過 new 的形式,而是交給Spring配置創建對象;
- AOP:面向切面編程,擴展功能而不用修改代碼;(通常用於日誌監控、登陸操作等);
IOC是典型的工廠模式,通過工廠去注入對象,AOP則是代理模式的體現。
Spring提供了一站式的框架,Java EE三層結構中,每一層Spring都提供瞭解決方案:
- Controller(Web服務層):Spring MVC;
- Service(業務處理層):Spring IOC、AOP;
- Dao:Mybatis、jdbcTemplated、Mybatis-Spring整合;
Spring IOC
IOC即控制反轉,把對象的創建交給了Spring管理,IOC的使用有兩種方式:
- 通過配置文件;
- 通過註解;
IOC的底層原理:
- XML配置文件;
- dom4j解析XML配置文件,得到需要創建對象的全路徑名;
- 利用工廠設計模式,通過反射產生對象;
對象的創建過程:
- 創建XML配置文件,配置要創建的對象的類;
示例 <bean id="student" class="com.tulun.bean.Student1"/>
- 創建工廠類,利用dom4j解析配置文件,通過反射創建對象;
//大概原理
public class UserFactory {
public static User getBean() {
//利用dom4j解析配置文件,通過id屬性值來獲取到類的全路徑名
String path = "com.tulun.bean.Student1";
//通過反射創建對象
Class c = Class.forName(path);
//創建對象
User user = (User) c.newInstance();
return user;
}
}
IOC的使用(基於配置)
使用步驟:
- 引入依賴;
- 創建類,在類中添加方法;
- 創建Spring的XML配置文件,配置需要創建對象的類;
- 使用;
需要引入的Spring的基本依賴包:
<!--Spring 基本核心jar包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
Spring創建對象的方式
Spring通過配置文件創建對象的方式(即bean實例化的方式)主要有三種:
- 通過無參構造;
- 通過靜態工廠創建;
- 通過一般工廠創建;
代碼示例:
這三種方式需要創建的對象都是Student1的對象:
public class Student1 {
public void show() {
System.out.println("Student1.show()...");
}
}
一、通過無參構造
配置文件 bean1.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-3.0.xsd">
<!--創建Student對象
id和class屬性必填
id屬性:起名稱,名稱可以隨便給
class屬性:要讓Spring管理的類的全路徑名
//這也是實例化bean的第一種方式:通過無參構造(必須要有無參構造,否則會拋出異常)
-->
<bean id="student" class="com.tulun.bean.Student1"/>
</beans>
測試:
public class TestDemo1 {
public static void main(String[] args) {
//加載Spring配置文件,創建對象
ApplicationContext context = new ClassPathXmlApplicationContext("bean實例化/bean1.xml");
Student1 student = (Student1) context.getBean("student"); //參數是id
student.show();
}
}
二、使用靜態工廠創建
添加靜態工廠類:
public class StaticFactory {
public static Student1 getBean() {
return new Student1();
}
}
配置文件需要這樣寫,bean2.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-3.0.xsd">
<!--實例化bean的第2種方式-->
<!--通過靜態工廠創建Student類-->
<bean id="student1" class="com.tulun.factory.StaticFactory" factory-method="getBean"></bean>
</beans>
測試:
public class TestDemo2 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean實例化/bean2.xml");
Student1 student = (Student1)context.getBean("student1");
student.show();
}
}
三、通過一般工廠創建:
添加一般工廠類:
public class Factory {
public Student1 getBean() {
return new Student1();
}
}
這個方法實例化bean的時候,我們需要先得到工廠類對象,所以這個時候的配置文件bean3.xml是:
<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-3.0.xsd">
<!--實例化bean的第三種方式 通過一般工廠-->
<!--1、先創建工廠對象-->
<bean id="factory" class="com.tulun.factory.Factory"/>
<!--2、用工廠來創建bean實例對象-->
<bean id="student1" factory-bean="factory" factory-method="getBean"/>
</beans>
測試:
public class TestDemo3 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean實例化/bean3.xml");
Student1 student = (Student1)context.getBean("student1");
student.show();
}
}
Spring依賴注入的方式
以上是Spring創建對象的方式,現在來說說Spring如何給屬性賦值,也就是依賴注入(DI);
Java中給屬性賦值的方式有主要三種:
- 通過有參構造函數;
- 通過set方法;
- 通過接口;
在Spring裏面我們主要使用的給屬性賦值的方式有兩種:
- 有參構造;
- set方法;
代碼示例:
依賴注入主要是給Student2對象進行屬性注入:
public class Student2 {
private String name;
//通過set方法個屬性賦值的時候,先創建的是一個無參的對象
public Student2() {}
public Student2(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show() {
System.out.println("Student2.show()...");
}
}
一、通過有參構造
配置文件nature1.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-3.0.xsd">
<!--通過有參數構造進行屬性注入-->
<bean id="student" class="com.tulun.bean.Student2">
<constructor-arg name="name" value="張三"></constructor-arg>
</bean>
</beans>
測試:
public class TestDemo1 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("屬性的注入/nature1.xml");
Student2 student = (Student2)context.getBean("student");
System.out.println(student.getName());
student.show();
}
}
二、通過set方法:
這個被創建對象的類一定要有set方法,不然報錯;
nature2.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-3.0.xsd">
<!--通過set方法進行屬性注入-->
<bean id="student" class="com.tulun.bean.Student2">
<property name="name" value="李四"></property>
</bean>
</beans>
測試:
public class TestDemo2 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("屬性的注入/nature2.xml");
Student2 student = (Student2)context.getBean("student");
System.out.println(student.getName());
student.show();
}
}
複雜屬性的依賴注入
上述我們是對簡單數據類型的屬性進行依賴注入,那麼接下來就是複雜屬性的依賴注入,複雜屬性包括對象、數組、map、List、Properties(配置文件);
先來說說對象的注入:
先創建一個dao層的類:
public class User {
public void add() {
System.out.println("User.dao()");
}
}
再來一個Service層的對象:
public class UserService {
private User user;
//需要添加set方法纔可以給屬性賦值
public void setUser(User user) {
this.user = user;
}
public void add(){
user.add();
}
}
現在來寫配置文件nature3.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-3.0.xsd">
<!--對象屬性注入-->
<!--創建dao層對象-->
<bean id="userDao" class="com.tulun.dao.User"></bean>
<!--創建Service層對象-->
<bean id="userService" class="com.tulun.service.UserService">
<!--在service需要使用dao層對象-->
<property name="user" ref="userDao"/>
</bean>
</beans>
其實只要注意對象的注入的時候,後面那個標籤不是value,而是 ref 就好了!
測試:
public class TestDemo3 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("屬性的注入/複雜屬性的注入/nature3.xml");
UserService userService = (UserService)context.getBean("userService");
userService.add();
}
}
下來就是數組、List、map和properties屬性的注入了:
需要創建對象的類是Student3:
public class Student3 {
private String name;
private String[] str;
private List<String> list;
private Map<String,String> map;
private Properties properties;
public void setName(String name) {
this.name = name;
}
public void setStr(String[] str) {
this.str = str;
}
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;
}
@Override
public String toString() {
return "Student3{" +
"name='" + name + '\'' +
", 數組=" + Arrays.toString(str) +
", list=" + list +
", map=" + map +
", properties=" + properties +
'}';
}
}
他的配置文件nature4.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-3.0.xsd">
<!--數組屬性的注入-->
<bean id="student1" class="com.tulun.bean.Student3">
<property name="str">
<list>
<value>1</value>
<value>2</value>
</list>
</property>
</bean>
<!--list屬性的注入-->
<bean id="student2" class="com.tulun.bean.Student3">
<property name="list">
<list>
<value>張三</value>
<value>李四</value>
</list>
</property>
</bean>
<!--map屬性的注入-->
<bean id="student3" class="com.tulun.bean.Student3">
<property name="map">
<map>
<entry key="tulun" value="lzq"></entry>
<entry key="tulun" value="lcx"></entry>
</map>
</property>
</bean>
<!--properties屬性的注入-->
<bean id="student4" class="com.tulun.bean.Student3">
<property name="properties">
<props>
<prop key="DriverClass">com.mysql.jdbc.Driver</prop>
</props>
</property>
</bean>
</beans>
測試:
public class TestDemo4 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("屬性的注入/複雜屬性的注入/nature4.xml");
test1(context);
test2(context);
test3(context);
test4(context);
}
//測試數組
private static void test1(ApplicationContext context) {
Student3 student = (Student3)context.getBean("student1");
System.out.println(student.toString());
}
//測試list
private static void test2(ApplicationContext context) {
Student3 student = (Student3)context.getBean("student2");
System.out.println(student.toString());
}
//測試map
private static void test3(ApplicationContext context) {
Student3 student = (Student3)context.getBean("student3");
System.out.println(student.toString());
}
//測試文件
private static void test4(ApplicationContext context) {
Student3 student = (Student3)context.getBean("student4");
System.out.println(student.toString());
}
}
IOC的使用(基於註解)
使用步驟:
- 引入依賴;
- 配置XML文件,開啓掃描類;
- 創建對應的類,添加註解,一般用@Component;
- 測試使用;
依賴和上面的一樣;
在常用的註解@Component下還衍生了三個註解:
- @Controller(Web層);
- @Service(業務層);
- @Repository(dao層);
他們的作用都是一樣的,只是這樣是各層之間有了很高的區分度;
依賴注入的方式:
對象的依賴注入:
- @Autowired
- @Resource
簡單類型(基本屬性)的依賴注入:
- @Value
代碼示例:
創建類:
@Component(value = "user")
@Scope(value = "singleton") //設置單例
//相當於配置實現時裏面的id <bean id = "user" ...
public class User {
@Value(value = "1") //簡單屬性的注入
private int id;
public void add() {
System.out.println("User.add()"+id);
}
}
註解實現的配置文件,bean4.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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 開啓掃描 對包進行掃描,找相關的有註解的類,把這個類進行裝配-->
<context:component-scan base-package="com.tulun1"></context:component-scan>
</beans>
測試,測試我用的額 junit,它的 jar 包如下:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
測試代碼:
public class TestDemo1 {
@Test
public void test1() {
ApplicationContext context = new ClassPathXmlApplicationContext("註解實現/bean4.xml");
User user = (User)context.getBean("user");
user.add();
}
}
再來一個:
創建一個類:
@Component(value = "userService")
public class UserService {
@Autowired
//@Resource //這個也可以 需要添加參數的話就是User那個類註解裏面的
private User user; //這個User就是上面示例中的那個
public void add() {
user.add();
}
}
測試:
public class TestDemo2 {
@Test
public void test1() {
ApplicationContext context = new ClassPathXmlApplicationContext("註解實現/bean4.xml");
UserService userService = (UserService) context.getBean("userService");
userService.add();
}
}
所以拿註解來實現的話,就顯得特別簡單,而在IOC中,配置和註解一般是聯合使用的,其中:
- 創建對象(bean的實例化)是通過配置實現的;
- 依賴注入是通過註解實現的;
下面是一個配置和註解聯合使用的例子,有三層(Controller、Service、Dao),其中,Controller層中有Service層的對象,Service層中有Dao層對象,那麼代碼如下:
創建Dao層類:
public class TestDao {
@Value(value = "1")
private int test;
public void setTest(int test) {
this.test = test;
}
public void test() {
System.out.println("TestDao.test()"+test);
}
}
創建Service層類:
public class TestService {
@Autowired
private TestDao testDao;
public void setTestDao(TestDao testDao) {
this.testDao = testDao;
}
public void test() {
testDao.test();
}
}
創建Controlller層類:
public class TestController {
@Resource
private TestService testService;
public void setTestService(TestService testService) {
this.testService = testService;
}
public void test() {
testService.test();
}
}
因爲是配置和註解的聯合使用,所以需要在配置文件中開啓掃描、創建對象,那麼bean5.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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 開啓掃描 對包進行掃描,找相關的有註解的類,把這個類進行裝配-->
<context:component-scan base-package="com.tulun1"></context:component-scan>
<!--創建dao層對象-->
<bean id="dao" class="com.tulun1.dao.TestDao"></bean>
<!--創建service層對象-->
<bean id="service" class="com.tulun1.service.TestService">
<property name="testDao" ref="dao"></property>
</bean>
<!--創建controller層對象-->
<bean id="controller" class="com.tulun1.controller.TestController">
<property name="testService" ref="service"></property>
</bean>
</beans>
測試:
public class TestDemo3 {
@Test
public void test1() {
ApplicationContext context = new ClassPathXmlApplicationContext("配置和註解聯合使用/bean5.xml");
TestController testController = (TestController)context.getBean("controller");
testController.test();
}
}