Spring是分層的 Java SE/EE應用 full-stack 輕量級開源框架,以 IoC(Inverse Of Control:反轉控制)和 AOP(Aspect Oriented Programming:面向切面編程)爲內核。java
提供了展示層 SpringMVC和持久層 Spring JDBCTemplate以及業務層事務管理等衆多的企業級應用技術,還能整合開源世界衆多著名的第三方框架和類庫,逐漸成爲使用最多的Java EE 企業應用開源框架spring
Rod Johnson ( Spring 之父)express
2017年 9月份發佈了 Spring的最新版本 Spring5.0 通用版(GA)編程
方便解耦,簡化開發api
AOP 編程的支持session
聲明式事務的支持app
方便程序的測試框架
①導入 Spring 開發的基本包座標dom
②編寫 Dao 接口和實現類ide
③建立 Spring 核心配置文件
④在 Spring 配置文件中配置 UserDaoImpl
⑤使用 Spring 的 API 得到 Bean 實例
<properties> <spring.version>5.0.5.RELEASE</spring.version> </properties> <!--導入spring的context座標,context依賴core、beans、expression--> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> </dependencies>
public interface UserDao { public void save(); } public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("UserDao save method running...."); } }
在類路徑下(resources)建立applicationContext.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"> </beans>
<?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="userDao" class="com.itheima.dao.impl.UserDaoImpl"></bean> //bean標籤:在Spring的容器中 聲明一個Bean對象 //id屬性:爲bean類的惟一標識,不可重複 //class屬性:建立的bean全類名 </beans>
@Test public void test1(){ ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao = (UserDao) app.getBean("userDao"); userDao.save(); }
用於配置對象交由Spring 來建立。
默認狀況下它調用的是類中的無參構造函數,若是沒有無參構造函數則不能建立成功。
基本屬性:
id:Bean實例在Spring容器中的惟一標識
class:Bean的全限定名稱
scope:指對象的做用範圍,取值以下:
取值範圍 | 說明 |
---|---|
singleton | 默認值,單例的(經常使用) |
prototype | 多例的 |
request | WEB 項目中,Spring 建立一個 Bean 的對象,將對象存入到 request 域中 |
session | WEB 項目中,Spring 建立一個 Bean 的對象,將對象存入到 session 域中 |
global session | WEB 項目中,應用在 Portlet 環境,若是沒有 Portlet 環境那麼globalSession 至關於 session |
1)當scope的取值爲singleton時
Bean的實例化個數:1個
Bean的實例化時機:當Spring核心文件被加載時,實例化配置的Bean實例
Bean的生命週期:
對象建立:當應用加載,建立容器時,對象就被建立了
對象運行:只要容器在,對象一直活着
對象銷燬:當應用卸載,銷燬容器時,對象就被銷燬了
2)當scope的取值爲prototype時
Bean的實例化個數:多個
Bean的實例化時機:當調用getBean()方法時實例化Bean
對象建立:當使用對象時,建立新的對象實例
對象運行:只要對象在使用中,就一直活着
對象銷燬:當對象長時間不用時,被 Java 的垃圾回收器回收了
init-method:指定類中的初始化方法名稱
destroy-method:指定類中銷燬方法名稱
1) 使用無參構造方法實例化
它會根據默認無參構造方法來建立類對象,若是bean中沒有默認無參構造函數,將會建立失敗
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
2) 工廠靜態方法實例化
建立一個工廠類(StaticFactoryBean),在工廠類中 包含靜態而且返回對象的方法(createUserDao)
工廠的靜態方法返回Bean實例
public class StaticFactoryBean { public static UserDao createUserDao(){ return new UserDaoImpl(); } }
在ApplicationContext.xml配置文件中,class屬性聲明 靜態工廠類 的全類名,而且添加 factory-method 屬性,屬性值爲工廠類中的靜態方法名
當Spring讀取配置文件時,會根據 factory-method 屬性,調用靜態方法,返回UserDaoImpl對象
<bean id="userDao" class="com.itheima.factory.StaticFactoryBean" factory-method="createUserDao" /> //等價於:UserDao userDao = StaticFactoryBean.createUserDao();
3) 工廠實例方法實例化
建立一個工廠類(DynamicFactoryBean),在工廠類中 包含非靜態而且返回對象的方法(createUserDao)
工廠的非靜態方法返回Bean實例
public class DynamicFactoryBean { public UserDao createUserDao(){ return new UserDaoImpl(); } }
當工廠類的方法爲非靜態時,那麼就不能直接進行調用,就須要先讓Spring容器建立工廠類的對象,
再經過 factory-bean , factory-method 屬性進行返回
<bean id="factoryBean" class="com.itheima.factory.DynamicFactoryBean"/> //等價於:factoryBean = new DynamicFactoryBean; <bean id="userDao" factory-bean="factoryBean" factory-method="createUserDao"/> //等價於:UserDao userDao = factoryBean.createUserDao();
①建立 UserService,UserService 內部在調用 UserDao的save() 方法
public class UserServiceImpl implements UserService { @Override public void save() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao = (UserDao) applicationContext.getBean("userDao"); userDao.save(); } }
②將 UserServiceImpl 的建立權交給 Spring
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl"/>
③從 Spring 容器中得到 UserService 進行操做
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = (UserService) applicationContext.getBean("userService"); userService.save();
依賴注入(Dependency Injection):它是 Spring 框架核心 IOC 的具體實現。
在編寫程序時,經過控制反轉,把對象的建立交給了 Spring,可是代碼中不可能出現沒有依賴的狀況。
IOC 解耦只是下降他們的依賴關係,但不會消除。例如:業務層仍會調用持久層的方法。
那這種業務層和持久層的依賴關係,在使用 Spring 以後,就讓 Spring 來維護了。
簡單的說,就是坐等框架把持久層對象傳入業務層,而不用咱們本身去獲取
①構造方法
建立有參構造
public class UserServiceImpl implements UserService { @Override public void save() { private UserDao userDao; public userServiceImpl() { } public userServiceImpl(UserDao userDao) { this.userDao = userDao; } public void seva() { userDao.test(); } } }
配置Spring容器調用有參構造時進行注入
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/> <bean id="userService" class="com.itheima.service.impl.UserServiceImpl"> <constructor-arg name="userDao" ref="userDao"></constructor-arg> </bean>
②set方法
在UserServiceImpl中添加setUserDao方法
public class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void save() { userDao.save(); } }
配置Spring容器調用set方法進行注入
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/> <bean id="userService" class="com.itheima.service.impl.UserServiceImpl"> <property name="userDao" ref="userDao"/> </bean>
set方法:P命名空間注入
P命名空間注入本質也是set方法注入,但比起上述的set方法注入更加方便,主要體如今配置文件中,以下:
首先,須要引入P命名空間:
xmlns:p="http://www.springframework.org/schema/p"
其次,須要修改注入方式
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl" p:userDao-ref="userDao"/>
上面的操做,都是注入的引用Bean,除了對象的引用能夠注入,普通數據類型,集合等均可以在容器中進行注入。
注入數據的三種數據類型
普通數據類型
引用數據類型
集合數據類型
其中引用數據類型,此處就再也不贅述了,以前的操做都是對UserDao對象的引用進行注入的,下面將以set方法注入爲例,演示普通數據類型和集合數據類型的注入。
Bean的依賴注入的數據類型
(1)普通數據類型的注入
public class UserDaoImpl implements UserDao { private String company; private int age; public void setCompany(String company) { this.company = company; } public void setAge(int age) { this.age = age; } public void save() { System.out.println(company+"==="+age); System.out.println("UserDao save method running...."); } }
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"> <property name="company" value="XXX"></property> <property name="age" value="15"></property> </bean>
(2)集合數據類型(List
public class UserDaoImpl implements UserDao { private List<String> strList; public void setStrList(List<String> strList) { this.strList = strList; } public void save() { System.out.println(strList); System.out.println("UserDao save method running...."); } }
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"> <property name="strList"> <list> <value>aaa</value> <value>bbb</value> <value>ccc</value> </list> </property> </bean>
(3)集合數據類型(List
public class UserDaoImpl implements UserDao { private List<User> userList; public void setUserList(List<User> userList) { this.userList = userList; } public void save() { System.out.println(userList); System.out.println("UserDao save method running...."); } }
<bean id="u1" class="com.itheima.domain.User"/> <bean id="u2" class="com.itheima.domain.User"/> <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"> <property name="userList"> <list> <bean class="com.itheima.domain.User"/> <bean class="com.itheima.domain.User"/> <ref bean="u1"/> <ref bean="u2"/> </list> </property> </bean>
(4)集合數據類型( Map<String,User> )的注入
public class UserDaoImpl implements UserDao { private Map<String,User> userMap; public void setUserMap(Map<String, User> userMap) { this.userMap = userMap; } public void save() { System.out.println(userMap); System.out.println("UserDao save method running...."); } }
<bean id="u1" class="com.itheima.domain.User"/> <bean id="u2" class="com.itheima.domain.User"/> <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"> <property name="userMap"> <map> <entry key="user1" value-ref="u1"/> <entry key="user2" value-ref="u2"/> </map> </property> </bean>
(5)集合數據類型(Properties)的注入
public class UserDaoImpl implements UserDao { private Properties properties; public void setProperties(Properties properties) { this.properties = properties; } public void save() { System.out.println(properties); System.out.println("UserDao save method running...."); } }
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"> <property name="properties"> <props> <prop key="p1">aaa</prop> <prop key="p2">bbb</prop> <prop key="p3">ccc</prop> </props> </property> </bean>
實際開發中,Spring的配置內容很是多,這就致使Spring配置很繁雜且體積很大,因此,能夠將部分配置拆解到其餘配置文件中,而在Spring主配置文件經過import標籤進行加載
<import resource="applicationContext-xxx.xml"/>
applicationContext:接口類型,表明應用上下文,能夠經過其實例得到 Spring 容器中的 Bean 對象
1)ClassPathXmlApplicationContext
它是從類的根路徑下加載配置文件 推薦使用這種
2)FileSystemXmlApplicationContext
它是從磁盤路徑上加載配置文件,配置文件能夠在磁盤的任意位置。
3)AnnotationConfigApplicationContext
當使用註解配置容器對象時,須要使用此類來建立 spring 容器。它用來讀取註解。
public Object getBean(String name) throws BeansException { assertBeanFactoryActive(); return getBeanFactory().getBean(name); } public <T> T getBean(Class<T> requiredType) throws BeansException { assertBeanFactoryActive(); return getBeanFactory().getBean(requiredType); }
其中,當參數的數據類型是字符串時,表示根據Bean的id從容器中得到Bean實例,返回是Object,須要強轉。
當參數的數據類型是Class類型時,表示根據類型從容器中匹配Bean實例,當容器中相同類型的Bean有多個時,則此方法會報錯
getBean()方法使用
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService1 = (UserService) applicationContext.getBean("userService"); UserService userService2 = applicationContext.getBean(UserService.class);