spring 優點
- 方便解耦,簡化開發(高內聚低耦合)
- Spring就是一個大廠(容器),可以將所有物件建立和依賴關係維護,交給Spring管理
- AOP程式設計的支援
- Spring提供面向切面程式設計,可以方便的實現對程式進行許可權攔截、執行監控等功能
- 宣告式事務的支援
- 只需要通過配置基於可以完成對事務的管理,而無需手動程式設計
- 方面程式的測試
- spring不排斥各種優秀的開源框架,其內部提供了對各種優秀框架(如Struts、Hibernate、MyBatis、Quartz等)的直接支援
- 降低JavaEEAPI的使用難度
- spring對JAVAEE開發中非常難用的一些API(JDBC,JavaMail,遠端呼叫等),都提供了封裝,使這些API應用難度大大降低
案例入門 IOC
-
匯入jar包
- 4+1:四個核心(beans、core、context、expression)+1個依賴(commons-loggins..jar)
-
目標類
-
提供UserService介面和實現
-
獲得UserService實現類的例項
-
之前開發,直接new一個物件即可,學習spring之後,將由Spring建立物件例項-->IOC控制反轉(Inverse of Control)之後需要例項物件時,從spring工廠(容器)中獲得,需要將實現類的全限定名稱配置到xml檔案中
``
public interface UserService { public void addUser(); } public class UserServiceImpl implements UserService{ @Override public void addUser() { System.out.println("Hello world"); } } 複製程式碼
@Test public void test(){ //從spring容器獲得 //1獲得容器 String xmlPath = "com/adolph/ioc/applicationContext.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); //2獲得內容--不需要自己new,都是從spring容器中獲得 UserService userService = (UserService) applicationContext.getBean("userServiceId"); userService.addUser(); } 複製程式碼
-
-
配置檔案
- 位置:任意,開發中一般在classpath下
- 名稱:任意,開發中常用applicationContext.xml
- 內容:新增schema約束
``
<?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"> <!--配置server <bean>配置需要建立的物件 id:用於之後從spring容器獲得例項時使用的 class:需要建立例項的全限定類名 --> <bean id="userServiceId" class="com.adolph.ioc.UserServiceImpl"></bean> </beans> 複製程式碼
案例入門 DI
-
DI(Dependency Injection)依賴注入
-
is a:是一個,繼承
-
has a:有一個,成員變數,依賴
class B{
private A a; //B類依賴A
}
依賴:一個物件需要使用另一個物件
注入:通過setter方法進行另一個物件的例項設定
例如:
class BookService{ //之前開發(service和dao耦合) private BookDao bookDao = new BookDaoImpl(); //spring之後(解耦:service實現類使用dao介面,不知道具體的實現類) private BookDao bookDao; } 複製程式碼
-
模擬spring執行過程
建立service例項:BookServlice bookService = new BookService() -->IOC
建立dao例項:BookDao bookDao = new BookDaoImpl() -->IOC
將dao設定給service:bookService.setBookDao(bookDao) -->DI
目標類
建立BookService介面和實現類
建立BookDao介面和實現
將dao和service配置xml檔案
``
<!--<property>用於進行屬性名注入 name:bean的屬性名,通過setter方法獲得setBookDao ref:另一個bean的id值的引用##--> <!--建立service執行過程--> <bean id="bookServiceId" class="com.adolph.di.BookServiceImpl"> <property name="bookDao" ref="bookDaoId"></property> </bean> <bean id="bookDaoId" class="com.adolph.di.BookDaoImpl"></bean> 複製程式碼
核心 API
- BeanFactory:這是一個工廠,用於生成任意bean。採用延時載入,第一次getBean時才會初始化Bean
- ApplicationContext:是BeanFactory的子介面,功能更強大
- 國際化處理
- 事件傳遞
- Bean自動裝配
- 各種不同應用層Context的實現
- CalssPathXmlApplicationContext用於載入classpath(類路徑、src)下指定的xml
- FileSystemXmlApplicationCotext 用於載入指定碟符下的xml
基於XML
1、例項化方式
3種備案例項化方式:預設構造、靜態工廠、例項工廠
-
預設構造
- 必須提供預設構造
-
靜態工廠
-
常用於與spring整合其他框架(工具)
-
靜態工廠:用於生成例項物件,所有的方法必須是static
-
例項工廠
- 必須先有工廠例項物件,通過例項物件建立物件。提供所有的方法都是“非靜態“的。
``
public class MyBeanFactory { /** * 建立例項 * @return */ public UserService createService(){ return new UserServiceImpl(); } } 複製程式碼
``
<!--建立工廠例項--> <bean id="myBeanFactory" class="com.adolph.inject.b_static_factory.MyBeanFactory"></bean> <!--獲得userService factory-bean 確定工廠例項 factory-method 確定普通方法 --> <bean id="userService" factory-bean="myBeanFactory" factory-method="createService"></bean> 複製程式碼
-
2、Bean種類
- 普通bean:之前操作的都是普通bean。,spring直接建立A例項,並返回
- FactoryBean:是一個特殊的bean具有工廠生成物件的能力,只能生成特定的物件。bean必須使用Factory介面,此介面提供方法getObject()方法用於獲得特定bean先建立FB例項,使用呼叫getObject()方法,並返回方法的返回值。
FB fb = new FB(); return fb.getObject();
- BeanFactory和FactoryBean對比
- BeanFactory:工廠,用於生產任意的bean
- FactoryBean:特定bean,用於生成另一個特定的bean。 例如:ProxyFactoryBean,此工廠bean用於生產代理。獲得代理物件例項。AOP的使用
3、作用域
作用域:用於確定spring建立bean例項個數
類別 | 說明 |
---|---|
singleton | 在spring Ioc容器中僅存在一個Bean例項,Bean亦單例方式存在,預設值 |
prototype | 每次從容器中呼叫Bean時,都返回一個新的例項,即每次呼叫getBean()時,相當於執行new XXBean() |
request | 每次HTTP請求都會建立一個新的Bean。該作用域僅適用於WebApplicationContext環境 |
session | 同一個HTTP Session 共享一個Bean,不同Session使用不同的Bean,僅適用於WebApplicationContext環境 |
globalSession | 一般用於Portlet應用環境,該作用域僅適用於WebApplicationContext環境 |
-
取值
- singleton 單例,預設值。
- prototype 多例,每執行一次getBean將獲得一個例項。例如:struts整合spring,配置action多例
-
配置資訊
<bean id="userService" class="com.adolph.inject.b_static_factory.UserServiceImpl" scope="prototype"></bean>
複製程式碼
4、生命週期
4.1、初始化和銷燬
-
目標方法執行或執行後,將進行初始化或銷燬
<bean id="" class="" init-method="初始化方法名稱" destroy-method="銷燬的方法名稱"> 複製程式碼
例項
public void myInit(){
System.out.println("初始化");
}
public void myDestroy(){
System.out.println("銷燬");
}
}
複製程式碼
//要求:1,容器必須close,銷燬方法執行,2、必須是單例的
//此方法介面中沒有定義,實現類提供
classPathXmlApplicationContext.close();
複製程式碼
<!--
init-method:用於配置初始化方法,準備資料
destroy-method:用於配置銷燬方法,清理資源
-->
<bean id="userServiceId" class="com.adolph.ioc.UserServiceImpl" init-method="myInit" destroy-method="myDestroy"></bean>
複製程式碼
4.2、BeanPostProcessor 後處理Bean
-
spring 提供一種機制、只要實現介面BeanPostProcessor,並將實現類提供給spring容器,spring容器將自動執行,在初始化方法前執行before(),在初始化方法後執行after() 。配置
-
spring提供工廠勾子,用於修改例項物件,可以生成代理物件,是AOP底層。
模擬:
//將a的例項物件傳遞給後處理bean,可以生成代理物件並放回 A a = new A(); a = B.before(a); a.init(); a = B.after(a) //生成代理物件,目的在目標方法前後執行(例如:開啟事務,提交事務) a.addUser(); a.destroy(); public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("前方法" + beanName); return null; } @Override public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException { System.out.println("後方法" + beanName); return Proxy.newProxyInstance(MyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler(){ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("------開啟事務"); // 執行目標方法 Object obj = method.invoke(bean, args); System.out.println("------提交事務"); return obj; } }); } } 複製程式碼
<bean class="com.adolph.ioc.MyBeanPostProcessor"></bean>
複製程式碼
4.3、setter方法
``
<bean id="person" class="com.adolph.stter.Person">
<property name="pname" value="jack"></property>
<property name="age">
<value>18</value>
</property>
<property name="address" ref="address"></property>
</bean>
<bean id="address" class="com.adolph.stter.Address">
<property name="addr" value="湖南"></property>
<property name="tel" value="177*****43"></property>
</bean>
複製程式碼
4.4P名稱空間
,預設:xmlns=""
顯示:xmlns:別名=""
4.5、SqEL
- 對進行統一編碼,所有內容都是使用value
- #{123}、#{'jack'}:數字、字串
- #{beanId}:另一個bean引用
- #{beanId.propName}:運算元據
- #{beanId.toString}:執行方法
- #{T(類).欄位|方法}:靜態方法或欄位
4.6、集合注入
public class CollData {
private String[] arrrayData;
private List<String> listData;
private Set<String> setData;
private Map<String,String> mapData;
private Properties properties;
public String[] getArrrayData() {
return arrrayData;
}
public void setArrrayData(String[] arrrayData) {
this.arrrayData = arrrayData;
}
public List<String> getListData() {
return listData;
}
public void setListData(List<String> listData) {
this.listData = listData;
}
public Set<String> getSetData() {
return setData;
}
public void setSetData(Set<String> setData) {
this.setData = setData;
}
public Map<String, String> getMapData() {
return mapData;
}
public void setMapData(Map<String, String> mapData) {
this.mapData = mapData;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "CollData{" +
"arrrayData=" + Arrays.toString(arrrayData) +
", listData=" + listData +
", setData=" + setData +
", mapData=" + mapData +
", properties=" + properties +
'}';
}
}
複製程式碼
<!--
集合的注入都是給<property>新增子標籤
陣列:<array>
List:<list>
Set:<set>
Map:<map>
Properties:<props>
普通資料:<value>
引用資料:<ref>
-->
<bean id="collData" class="com.adolph.coll.CollData">
<property name="arrrayData">
<array>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
</array>
</property>
<property name="listData">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
</list>
</property>
<property name="setData">
<set>
<value>1</value>
<value>2</value>
<value>3</value>
</set>
</property>
<property name="mapData">
<map>
<entry key="1" value="a"></entry>
<entry key="2" value="b"></entry>
<entry key="3" value="c"></entry>
</map>
</property>
<property name="properties">
<props>
<prop key="高富帥">嫐</prop>
<prop key="白富美">嬲</prop>
<prop key="屌絲">挊</prop>
</props>
</property>
</bean>
複製程式碼
基於註釋
- 註解:就是一個類,使用@註解名稱
- 開發中:使用註解 取代xml配置檔案。
-
@Component("id")取代
-
wen開發,提供3個@Component註解衍生註解(功能一樣)
- @Repository:dao層
- @Service:service層
- @Controller:web層
-
依賴注入,可以給私有欄位設定,也可以給setter方法設定
- 普通值:@Value("")
- 引用值:
- 方式1:按照【型別】注入
- @Autowired
- 方式2:按照【名稱】注入1
- @Autowired
- @Qualifier("名稱")注入
- 方式3:按照【名稱】注入2
- @Resource(“名稱”)
- 方式1:按照【型別】注入
-
@Test public void test() { String xmlPath = "com/adolph/web/beans.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); StudentAction studentAction = applicationContext.getBean("studentActionId", StudentAction.class); studentAction.execute(); } Controller("studentActionId") public class StudentAction { @Autowired private StudentService studentService; public void execute(){ studentService.add(); } } @Service public class StudentServiceImpl implements StudentService { private StudentDao studentDao; @Autowired @Qualifier("studentDaoId") public void setStudentDao(StudentDao studentDao) { this.studentDao = studentDao; } @Override public void add() { studentDao.add(); } } @Repository("studentDaoId") public class StudentDaoImpl implements StudentDao{ @Override public void add() { System.out.println("dao"); } } 複製程式碼
生命週期
初始化:@PostConstruct
銷燬:@PreDestroy
作用域:
@Scope("prototype") 多例
-
註解使用前提,新增名稱空間,讓spring掃描含有註解類**
<!--元件掃描--> <context:component-scan base-package="com.adolph.annotation"></context:component-scan> 複製程式碼