spring5æ¡æ¶
- ä¸ãSpring æ¡æ¶æ¦è¿°
-
- å ¥é¨æ¡ä¾
-
- 1ãä¸è½½ Spring5
- 2ãæå¼ideaï¼å建æ®é Java å·¥ç¨
- 3ãå¯¼å ¥ Spring5 ç¸å ³ jar å
- 4ãå建æ®éç±»ï¼å¨è¿ä¸ªç±»å建æ®éæ¹æ³
- 5ãå建 Spring é ç½®æ件ï¼å¨é ç½®æ件é ç½®å建对象
- 6ãè¿è¡æµè¯ä»£ç ç¼å
- äºãIOC容å¨
-
- 1ãIOC åºå±åç
- 2ãIOC æ¥å£ï¼BeanFactoryï¼
- 3ãIOC æä½ Bean 管çï¼åºäº xmlï¼
- 4ãIOC æä½ Bean 管çï¼åºäº 注解ï¼
- 5ãIOC æä½ Bean 管çï¼p å称空é´æ³¨å ¥ï¼
- 6ãIOC æä½ Bean 管çï¼xml æ³¨å ¥å ¶ä»ç±»åå±æ§ï¼
- 7ãIOC æä½ Bean 管çï¼xml æ³¨å ¥éåå±æ§ï¼
- 8ãIOC æä½ Bean 管çï¼FactoryBeanï¼
- 9ãIOC æä½ Bean 管çï¼beanä½ç¨åï¼
- 10ãIOC æä½ Bean 管çï¼beançå½å¨æï¼
- 11ãIOC æä½ Bean 管çï¼xmlèªå¨è£ é ï¼
- 12ãIOC æä½ Bean 管çï¼å¤é¨å±æ§æ件ï¼
- 13ãIOC æä½ Bean 管çï¼åºäºæ³¨è§£æ¹å¼ï¼
- ä¸ãAop
-
- 1ãAOPï¼æ¦å¿µï¼
- 2ãAOPï¼åºå±åçï¼
- 3ãAOPï¼JDK å¨æ代çï¼
- 4ãAOPï¼æ¯è¯ï¼
- 5ãAOPï¼åå¤ï¼
- 6ãAOPï¼AspectJ 注解ï¼
- 7ãAOPï¼AspectJ é ç½®æ件ï¼
- åãJdbTemplate
-
- 1ãJdbcTemplateï¼æ¦å¿µååå¤ï¼
- 2ãJdbcTemplate æä½æ°æ®åºï¼æ·»å ï¼
- 3ãJdbcTemplate æä½æ°æ®åºï¼ä¿®æ¹åå é¤ï¼
- 4ãJdbcTemplate æä½æ°æ®åºï¼æ¥è¯¢è¿åæ个å¼ï¼
- 5ãJdbcTemplate æä½æ°æ®åºï¼æ¥è¯¢è¿å对象ï¼
- 6ãJdbcTemplate æä½æ°æ®åºï¼æ¥è¯¢è¿åéåï¼
- 7ãJdbcTemplate æä½æ°æ®åºï¼æ¹éæä½ï¼
- äºãäºå¡ç®¡ç
-
- 1ãäºå¡æä½ï¼äºå¡æ¦å¿µï¼
- 2ãäºå¡æä½ï¼æ建äºå¡æä½ç¯å¢ï¼
- 3ãäºå¡æä½ï¼Spring äºå¡ç®¡çä»ç»ï¼
- 4ãäºå¡æä½ï¼æ³¨è§£å£°æå¼äºå¡ç®¡çï¼
- 5ãäºå¡æä½ï¼å£°æå¼äºå¡ç®¡çåæ°é ç½®ï¼
- 6ãäºå¡æä½ï¼XML 声æå¼äºå¡ç®¡çï¼
- 7ãäºå¡æä½ï¼å®å ¨æ³¨è§£å¼åï¼
- å ãSpring5 æ°ç¹æ§
-
- 1ãSpring5 æ¡æ¶æ°åè½
-
- 1ãéè¿ä½¿ç¨æ³åçç¹æ§æé«å¯è¯»æ§
- 2ãæ´ä¸ª Spring æ¡æ¶æ代ç åºäº Java8ï¼è¿è¡æ¶å ¼å®¹ JDK9ï¼è®¸å¤ä¸å»ºè®®ä½¿ç¨çç±»åæ¹æ³å¨ä»£ç åºä¸å é¤
- 3ãSpring 5.0æ¡æ¶èªå¸¦äºéç¨çæ¥å¿å°è£
- 4ãSpring5 æ¡æ¶æ ¸å¿å®¹å¨æ¯æ@Nullable注解
- 5ãSpring5 æ ¸å¿å®¹å¨å½æ°å¼é£æ ¼GenericApplicationContext
- 6ãSpring5 æ¯ææ´å JUnit5
- 2ãSpring5 æ¡æ¶æ°åè½ï¼Webfluxï¼
-
- 1ãSpringWebfluxä»ç»
- 2ãååºå¼ç¼ç¨
- 3ãååºå¼ç¼ç¨ï¼ Reactor å®ç°ï¼
- 4ãWebflux æ§è¡æµç¨åæ ¸å¿ API
- 5ãSpringWebflux ï¼åºäºæ³¨è§£ç¼ç¨æ¨¡åï¼
- 6ãSpringWebflux ï¼åºäºå½æ°å¼ç¼ç¨æ¨¡åï¼
è¿æ¥è§é¢
ä¸ãSpring æ¡æ¶æ¦è¿°
1ãSpringæ¯ä¸ä¸ªå¼æºç è½»é级 Java SEï¼Java æ åçæ¬ï¼/Java EEï¼Java
ä¼ä¸çæ¬ï¼å¼ååºç¨æ¡æ¶
2ãSpring ç®åä¼ä¸çº§åºç¨ç¨åºå¼åï¼éä½å¼åçå¤ææ§
3ãSpring æä¸¤ä¸ªæ ¸å¿é¨åï¼IOC å Aop
ï¼1ï¼IOCï¼æ§å¶å转ï¼æå建对象çè¿ç¨äº¤ç» spring è¿è¡ç®¡çï¼å¯¹è±¡å®ä¾åï¼
ï¼2ï¼Aopï¼é¢ååé¢ï¼å¨ä¸ä¿®æ¹æºä»£ç çæ åµä¸ï¼è¿è¡åè½å¢å¼º
4ãSpring ç¹ç¹ï¼
ï¼1ï¼æ¹ä¾¿è§£è¦ï¼ç®åå¼å
ï¼2ï¼Aop ç¼ç¨æ¯æ
ï¼3ï¼æ¹ä¾¿ç¨åºçæµè¯ï¼junitæ¯æï¼
ï¼4ï¼æ¹ä¾¿åå ¶ä»æ¡æ¶è¿è¡æ´å
ï¼5ï¼æ¹ä¾¿è¿è¡äºå¡æä½
ï¼6ï¼éä½ API å¼åé¾åº¦
ï¼7ï¼Java æºç æ¯ç»å ¸å¦ä¹ èä¾
5ãé举 Spring çæ¬ 5.x 课ç¨è®²è§£
å ¥é¨æ¡ä¾
1ãä¸è½½ Spring5
å®ç½
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPB10MBR1TyElaNBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLyUDO5QzM0ATM0ATNwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
ï¼1ï¼éæ© Spring 稳å®çæ¬ 5.2.6 ï¼
ï¼2ï¼ä¸è½½å°å
è¿å ¥githubå°åï¼æ¾å° Access to Binaries ä½ç½®
è¿å ¥ Spring Framework Artifacts,æ¾å°ä¸è½½å°å ï¼https://repo.spring.io
è¿å ¥ï¼
æ¾å° Spring çä½ç½®ï¼å¤å¶å°åï¼
å¨ï¼https://repo.spring.io å°åæ¼æ¥å¤å¶çå 容ï¼https://repo.spring.io/release/org/springframework/spring/
ä¸è½½ï¼
ä¸è½½è§£åå°æ¬å°ï¼
jarå ï¼
é ç½®æ件ï¼
2ãæå¼ideaï¼å建æ®é Java å·¥ç¨
File --> New --> Project
å建ä¸ä¸ªæ®éç Java å·¥ç¨ï¼
3ãå¯¼å ¥ Spring5 ç¸å ³ jar å
spring模åï¼
springæ ¸å¿å®¹å¨ï¼
-
ï¼è¿ä¸ª jar æ件æ¯ææåºç¨é½è¦ç¨å°çï¼å®å å«è®¿é®é ç½®æ件ãå建å管ç bean 以åè¿è¡Inversion of Control / Dependency Injectionï¼IoC/DIï¼æä½ç¸å ³çææç±»ãå¦æåºç¨åªéåºæ¬çIoC/DI æ¯æï¼å¼å ¥spring-core.jar åspring-beans.jar æ件就å¯ä»¥äºãå¤é¨ä¾èµspring-coreï¼(CGLIB)ãBeans
-
ï¼è¿ä¸ª jar æ件å å« Spring æ¡æ¶åºæ¬çæ ¸å¿å·¥å ·ç±»ãSpring å ¶å®ç»ä»¶è¦é½è¦ä½¿ç¨å°è¿ä¸ªå éçç±»ï¼æ¯å ¶å®ç»ä»¶çåºæ¬æ ¸å¿ï¼å½ç¶ä½ ä¹å¯ä»¥å¨èªå·±çåºç¨ç³»ç»ä¸ä½¿ç¨è¿äºå·¥å ·ç±»ãå¤é¨ä¾èµCommons Loggingï¼ (Log4J)ãCore
-
Context
ï¼è¿ä¸ª jar æ件为 Spring æ ¸å¿æä¾äºå¤§éæ©å±ãå¯ä»¥æ¾å°ä½¿ç¨Spring ApplicationContextç¹æ§æ¶æéçå ¨é¨ç±»ï¼JDNI æéçå ¨é¨ç±»ï¼instrumentationç»ä»¶ä»¥åæ ¡éªValidation æ¹é¢çç¸å ³ç±»ã
å¤é¨ä¾èµspring-beans, (spring-aop)ã
-
ï¼spring表达å¼è¯è¨Expression
å¨ spring-framework-5.3.6\libs ç®å½ä¸æ¾å°åjar个å ï¼
å¤å¶ä¾èµå å°é¡¹ç®éï¼
å¨ideaéï¼å¯¼å ¥åæå¤å¶çä¾èµå ï¼
File --> Project Structure
Modules --> spring5_demo1 -->Dependencies --> +
1.JARS or Directories
æ·»å ä¾èµå ï¼
4ãå建æ®éç±»ï¼å¨è¿ä¸ªç±»å建æ®éæ¹æ³
package com.zzp.spring5;
public class User {
public void add(){
System.out.println("....User.add().....");
}
}
5ãå建 Spring é ç½®æ件ï¼å¨é ç½®æ件é ç½®å建对象
ï¼1ï¼Spring é ç½®æä»¶ä½¿ç¨ xml æ ¼å¼ï¼
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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">
<!-- é
ç½®User对象å建 -->
<bean id="user" class="com.zzp.spring5.User">
</bean>
</beans>
6ãè¿è¡æµè¯ä»£ç ç¼å
package com.zzp.spring5.test;
import com.zzp.spring5.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpring5 {
@Test
public void testAdd(){
// 1ãå è½½springé
ç½®æ件
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
// 2ãè·åé
ç½®å建ç对象
User user = context.getBean("user", User.class);
System.out.println(user);
user.add();
}
}
æ§è¡ç»æï¼
[email protected]
....User.add().....
å®æäº xmlé ç½® å建对象
äºãIOC容å¨
1ãIOC åºå±åç
IOC ï¼æ¦å¿µååçï¼ï¼
IOCï¼ æ§å¶å转ï¼Inversion of Controlï¼ç¼©å为IoCï¼ï¼æ¯é¢å对象ç¼ç¨ä¸çä¸ç§è®¾è®¡ååï¼å¯ä»¥ç¨æ¥åä½è®¡ç®æºä»£ç ä¹é´çè¦å度ã
å ¶ä¸æ常è§çæ¹å¼å«åä¾èµæ³¨å ¥ï¼Dependency Injectionï¼ç®ç§°DIï¼ï¼è¿æä¸ç§æ¹å¼å«âä¾èµæ¥æ¾âï¼Dependency Lookupï¼ã
éè¿æ§å¶å转ï¼å¯¹è±¡å¨è¢«å建çæ¶åï¼ç±ä¸ä¸ªè°æ§ç³»ç»å ææ对象çå¤çå®ä½å°å ¶æä¾èµç对象çå¼ç¨ä¼ éç»å®ãä¹å¯ä»¥è¯´ï¼ä¾èµè¢«æ³¨å ¥å°å¯¹è±¡ä¸ã
ä»ä¹æ¯IOCï¼
ï¼1ï¼æ§å¶å转ï¼æ对象å建å对象ä¹é´çè°ç¨è¿ç¨ï¼äº¤ç» Spring 管ç
ï¼2ï¼ä½¿ç¨ IOC ç®çï¼ä¸ºäºè¦åéä½
ï¼3ï¼ ä¸é¢åçå ¥é¨æ¡ä¾å°±æ¯ IOC å®ç°
IOC åºå±åçï¼
ï¼1ï¼xml 解æãå·¥å模å¼ãåå°
å¾ç»è®²è§£ IOC åºå±åçï¼
åå§æ¨¡å¼ï¼
å·¥å模å¼ï¼
IOC è¿ç¨ï¼
2ãIOC æ¥å£ï¼BeanFactoryï¼
1ãIOC ææ³åºäº IOC容å¨å®æï¼IOC 容å¨åºå±å°±æ¯å¯¹è±¡å·¥å
2ãSpring æä¾ IOC 容å¨å®ç°ä¸¤ç§æ¹å¼ï¼ï¼ä¸¤ä¸ªæ¥å£ï¼
-
ï¼IOC 容å¨åºæ¬å®ç°ï¼æ¯ Spring å é¨ç使ç¨æ¥å£ï¼ä¸æä¾å¼å人åè¿è¡ä½¿ç¨ãï¼æ³¨ï¼å è½½é ç½®æ件çæ¶åä¸ä¼å建对象ï¼å¨è·å 对象/ä½¿ç¨ æä¼å建对象ï¼BeanFactory
// 1ãå è½½springé ç½®æ件 BeanFactory context = new ClassPathXmlApplicationContext("bean1.xml");
-
ï¼BeanFactory æ¥å£çåæ¥å£ï¼æä¾ä¸ªæ´å¤æ´å¼ºå¤§çåè½ï¼ä¸è¬æä¾å¼å人åè¿è¡ä½¿ç¨ãï¼æ³¨ï¼å è½½é ç½®æ件çæ¶åå°±ä¼æå¨é ç½®æ件对象è¿è¡å建ï¼ApplicationContext
// 1ãå è½½springé ç½®æ件 ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
3ã
ApplicationContext
æ¥å£å®ç°ç±»ï¼
-
ï¼å ¨è·¯å¾FileSystemXmlApplicationContext
-
ï¼ç±»è·¯å¾ClassPathXmlApplicationContext
3ãIOC æä½ Bean 管çï¼åºäº xmlï¼
1ãä»ä¹æ¯ bean 管ç
Bean 管çæçæ¯ä¸¤ä¸ªæä½ï¼
ï¼1ï¼Spring å建对象
ï¼2ï¼Spring æ³¨å ¥å±æ§
2ãBean 管çæä½æ两ç§æ¹å¼ï¼
ï¼1ï¼åºäº xmlé ç½®æ件æ¹å¼å®ç°
ï¼2ï¼åºäºæ³¨è§£æ¹å¼å®ç°
åºäº xml æ¹å¼å建对象
xmlé ç½®æ件å 容
<!-- é
ç½®User对象å建 -->
<bean id="user" class="com.zzp.spring5.User"></bean>
â å¨ Springé ç½®æ件ä¸ï¼ä½¿ç¨ bean æ ç¾ï¼å¨æ ç¾éé¢æ·»å 对åºå±æ§ï¼å°±å¯ä»¥å®ç°å¯¹è±¡å建
â¡å¨ bean æ ç¾æå¾å¤å±æ§ï¼ä»ç»å¸¸ç¨çå±æ§ï¼
-
å±æ§ï¼å¯ä¸æ è¯id
-
å±æ§ï¼ç±»å ¨è·¯å¾ï¼å 类路å¾ï¼class
-
å±æ§ï¼ç±»ä¼¼name
å±æ§ å¯ä»¥æç¹æ®å符id
â¢å建对象çæ¶åï¼é»è®¤ä¹æ¯æ§è¡æ åæé æ¹æ³å®æ对象çå建
4ãIOC æä½ Bean 管çï¼åºäº 注解ï¼
ï¼1ï¼DIï¼ä¾èµæ³¨å ¥ï¼å°±æ¯æ³¨å ¥å±æ§
第ä¸ç§æ³¨å ¥æ¹å¼ï¼ä½¿ç¨ set æ¹æ³è¿è¡æ³¨å ¥
ï¼1ï¼å建类ï¼å®ä¹å±æ§å对åºç set æ¹æ³
/**
* æ¼ç¤ºä½¿ç¨ setæ¹æ³è¿è¡æ³¨å
¥å±æ§
*/
public class Book {
// å建å±æ§
private String bname;
private String bauthor;
// å建å±æ§å¯¹åºç setæ¹æ³
public void setBname(String bname){
this.bname = bname;
}
public void setBauthor(String bauthor) {
this.bauthor = bauthor;
}
}
ï¼2ï¼å¨ Spring é ç½®æ件é 置对象å建ï¼é ç½®å±æ§æ³¨å ¥
<bean id="book" class="com.zzp.spring5.Book">
<!-- 使ç¨propertyå®æå±æ§æ³¨å
¥
nameï¼ç±»éé¢å±æ§å称
valueï¼åå±æ§æ³¨å
¥çå¼
-->
<property name="bname" value="æçç»"></property>
<property name="bauthor" value="è¾¾æ©èç¥"></property>
</bean>
ï¼3ï¼å°æµè¯ï¼
å¨Book类添å ä¸ä¸ªè¾åºæ¹æ³ï¼
/**
* æ¼ç¤ºä½¿ç¨ setæ¹æ³è¿è¡æ³¨å
¥å±æ§
*/
public class Book {
....
public void testDemo(){
System.out.println(bname + "::" +bauthor);
}
}
æµè¯æ¹æ³ï¼
@Test
public void testBook1(){
// 1ãå è½½springé
ç½®æ件
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
// 2ãè·åé
ç½®å建ç对象
Book book = context.getBean("book", Book.class);
System.out.println(book);
book.testDemo();
}
æ§è¡ï¼
[email protected]
æçç»::è¾¾æ©èç¥
第äºç§æ³¨å ¥æ¹å¼ï¼ä½¿ç¨æåæ°æé è¿è¡æ³¨å ¥
ï¼1ï¼å建类ï¼å®ä¹å±æ§ï¼å建å±æ§å¯¹åºæåæ°æé æ¹æ³
/**
* 使ç¨æåæ°æé 注å
¥
*/
public class Orders {
// å建å±æ§
private String oname;
private String address;
// æåæ°æé
public Orders(String oname, String address) {
this.oname = oname;
this.address = address;
}
}
ï¼2ï¼å¨ Spring é ç½®æ件ä¸è¿è¡é ç½®
<!-- æåæ°æé 注å
¥å±æ§ -->
<bean id="orders" class="com.zzp.spring5.Orders">
<constructor-arg name="oname" value="çµè"></constructor-arg>
<constructor-arg name="address" value="China"></constructor-arg>
</bean>
ï¼3ï¼å°æµè¯
å¨Orders 类添å ä¸ä¸ªè¾åºæ¹æ³ï¼
/**
* 使ç¨æåæ°æé 注å
¥
*/
public class Orders {
...
public void ordersTest(){
System.out.println(oname + "::" +address);
}
}
æµè¯æ¹æ³ï¼
@Test
public void testOrders(){
// 1ãå è½½springé
ç½®æ件
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
// 2ãè·åé
ç½®å建ç对象
Orders orders = context.getBean("orders", Orders.class);
System.out.println(orders);
orders.ordersTest();
}
æ§è¡ï¼
[email protected]
çµè::China
5ãIOC æä½ Bean 管çï¼p å称空é´æ³¨å ¥ï¼
ï¼1ï¼ä½¿ç¨ p å称空é´æ³¨å ¥ï¼å¯ä»¥ç®ååºäº xmlé ç½®æ¹æ³ ï¼æ³¨ï¼äºè§£å³å¯ï¼
第ä¸æ¥ï¼æ·»å p å称空é´å¨ xmlé ç½®æ件ä¸
xmlns:p=âhttp://www.springframework.org/schema/pâ![]()
spring5架構一、Spring 架構概述二、IOC容器三、Aop四、JdbTemplate五、事務管理六、Spring5 新特性
第äºæ¥ï¼è¿è¡å±æ§æ³¨å ¥ï¼å¨ bean æ ç¾éé¢è¿è¡æä½
<!-- p å称空é´æ³¨å
¥ -->
<bean id="book" class="com.zzp.spring5.Book" p:bname="ä¹é³ç¥å" p:bauthor="æ åæ°"></bean>
åºå±ä¹æ¯setæ¹æ³æ³¨å ¥
ï¼2ï¼å°æµè¯
@Test
public void testBook1(){
// 1ãå è½½springé
ç½®æ件
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
// 2ãè·åé
ç½®å建ç对象
Book book = context.getBean("book", Book.class);
System.out.println(book);
book.testDemo();
}
æ§è¡ï¼
[email protected]
ä¹é³ç¥å::æ åæ°
6ãIOC æä½ Bean 管çï¼xml æ³¨å ¥å ¶ä»ç±»åå±æ§ï¼
1ãåé¢é
private String bname = âæçç»â; æè
<property name=âbnameâ value=âæçç»â>
ï¼1ï¼null å¼
å¨Book类添å ä¸ä¸ªå±æ§
address
public class Book {
// å建å±æ§
private String bname = "æçç»";
private String bauthor;
private String address;
// å建å±æ§å¯¹åºç setæ¹æ³
public void setBname(String bname){
this.bname = bname;
}
public void setBauthor(String bauthor) {
this.bauthor = bauthor;
}
public void setAddress(String address) {
this.address = address;
}
public void testDemo(){
System.out.println(bname + "::" +bauthor + "::" + address );
}
}
xmlé ç½®æ件ï¼æ·»å å±æ§
<bean id="book" class="com.zzp.spring5.Book">
<property name="bname" value="æçç»"></property>
<property name="bauthor" value="è¾¾æ©èç¥"></property>
<!-- nullå¼-->
<property name="address">
<null/>
</property>
</bean>
æ§è¡ï¼testBook1()
[email protected]
æçç»::è¾¾æ©èç¥::null
ï¼2ï¼å±æ§å¼å å«ç¹æ®ç¬¦å·
ä¼ ç»åæ³ä¼æ¥éï¼
éé¢ä¸è½ç´æ¥ç¨ â<< >>â 符å·ï¼å¯ä»¥ç¨è½¬ä¹ç¬¦å·ï¼"
< >
" `ç¸å½å¤§äºå°äºç¬¦å·ï¼
使ç¨
CDATA
ï¼
<bean id="book" class="com.zzp.spring5.Book">
<property name="bname" value="æçç»"></property>
<property name="bauthor" value="è¾¾æ©èç¥"></property>
<!-- å±æ§å¼å
å«ç¹æ®ç¬¦å·
1 æ<>è¿è¡è½¬ä¹ < >
2 æç¹æ®ç¬¦å·å
容åå°CDATA
-->
<property name="address">
<value><![CDATA[<<å京>>]]></value>
</property>
</bean>
æ§è¡ï¼testBook1()
[email protected]
æçç»::è¾¾æ©èç¥::<<å京>>
2ãæ³¨å ¥å±æ§ â å¤é¨ bean
ï¼1ï¼å建两个类 serviceç±» å daoç±»
ï¼2ï¼å¨ serviceç±»è°ç¨ daoç±»éé¢çæ¹æ³
daoæ¥å£ç±»
package com.zzp.spring5.dao;
public interface UserDao {
public void update();
}
daoå®ç°ç±»
package com.zzp.spring5.dao;
public class UserDaoImpl implements UserDao{
@Override
public void update() {
System.out.println(".......UserDao.update()........");
}
}
serviceç±»
package com.zzp.spring5.service;
public class UserService {
public void add(){
System.out.println("...UserService.add().....");
// åå§æ¹å¼ å建UserDao对象
// UserDao userDao = new UserDaoImpl();
// userDao.update();
}
}
ï¼3ï¼å¨ Spring é ç½®æ件ä¸è¿è¡é ç½®
UserServiceç±»:
public class UserService {
// å建UserDaoç±»åå±æ§ï¼çæsetæ¹æ³
private UserDao userDao;
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
public void add(){
System.out.println("...UserService.add().....");
userDao.update();
}
}
xmlé ç½®æ件ï¼
<!--1 serviceådao对象å建 -->
<bean id="userService" class="com.zzp.spring5.service.UserService">
<!-- 注å
¥userDao对象
nameå±æ§å¼ï¼ç±»éé¢å±æ§å称
refå±æ§å¼ï¼å建userDao对象beanæ ç¾idå¼
-->
<property name="userDao" ref="userDaoImpl"></property>
</bean>
<!-- å¤é¨bean -->
<bean id="userDaoImpl" class="com.zzp.spring5.dao.UserDaoImpl"></bean>
ï¼4ï¼å°æµè¯ï¼
@Test
public void testAdd(){
// 1ãå è½½springé
ç½®æ件
BeanFactory context = new ClassPathXmlApplicationContext("bean2.xml");
// 2ãè·åé
ç½®å建ç对象
UserService user = context.getBean("userService", UserService.class);
System.out.println(user);
user.add();
}
æ§è¡ï¼
[email protected]
...UserService.add().....
.......UserDao.update()........
3ãæ³¨å ¥å±æ§ â å é¨ bean
ï¼1ï¼ä¸å¯¹å¤å ³ç³»ï¼æ¯å¦ï¼é¨é¨ååå·¥
ä¸ä¸ªé¨é¨æå¤ä¸ªåå·¥ï¼ä¸ä¸ªåå·¥å±äºä¸ä¸ªé¨é¨
é¨é¨æ¯ä¸ï¼åå·¥æ¯å¤
ï¼2ï¼å¨å®ä½ç±»ä¹é´è¡¨ç¤ºä¸å¯¹å¤å ³ç³»ï¼å工表示æå±é¨é¨ï¼ä½¿ç¨å¯¹è±¡ç±»åå±æ§è¿è¡è¡¨ç¤º
//é¨é¨ç±»
public class Dept {
private String dname;
public void setDname(String dname) {
this.dname = dname;
}
@Override
public String toString() {
return "Dept{" +
"dname='" + dname + '\'' +
'}';
}
}
// å工类
public class Emp {
private String ename;
private String gender;
// åå·¥å±äºæä¸ä¸ªé¨é¨ï¼ä½¿ç¨å¯¹è±¡å½¢å¼è¡¨ç¤º
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;
}
public void setEname(String ename) {
this.ename = ename;
}
public void setGender(String gender) {
this.gender = gender;
}
public void add(){
System.out.println(ename + "::" +gender + "::" + dept);
}
}
ï¼3ï¼å¨ spring é ç½®æ件ä¸è¿è¡é ç½®
<!-- å
é¨bean -->
<bean id="emp" class="com.zzp.spring5.bean.Emp">
<!-- 设置两个æ®éå±æ§ -->
<property name="ename" value="Tom"></property>
<property name="gender" value="ç·"></property>
<!-- 设置对象类åå±æ§ -->
<property name="dept">
<bean id="dept" class="com.zzp.spring5.bean.Dept">
<property name="dname" value="å®ä¿é¨"></property>
</bean>
</property>
</bean>
ï¼4ï¼å°æµè¯ï¼
@Test
public void testBean3(){
// 1ãå è½½springé
ç½®æ件
BeanFactory context = new ClassPathXmlApplicationContext("bean3.xml");
// 2ãè·åé
ç½®å建ç对象
Emp emp = context.getBean("emp", Emp.class);
System.out.println(emp);
emp.add();
}
æ§è¡ï¼
[email protected]
Tom::ç·::Dept{dname='å®ä¿é¨'}
4ãæ³¨å ¥å±æ§ â 级èèµå¼
使ç¨ä¸é¢ç emp对象示ä¾ï¼
ï¼1ï¼ç¬¬ä¸ç§åæ³ï¼
ä¿®æ¹xmlé ç½®æ件ï¼
<!-- 级èèµå¼ -->
<bean id="emp" class="com.zzp.spring5.bean.Emp">
<!-- 设置两个æ®éå±æ§ -->
<property name="ename" value="Tom"></property>
<property name="gender" value="ç·"></property>
<!-- 级èèµå¼ -->
<property name="dept" ref="dept"></property>
</bean>
<bean id="dept" class="com.zzp.spring5.bean.Dept">
<property name="dname" value="è´¢å¡é¨"></property>
</bean>
æ§è¡ï¼testBean3()
com.zzp.spring5.bean.[email protected]6eceb130
Tom::ç·::Dept{dname='è´¢å¡é¨'}
ï¼2ï¼ç¬¬äºç§åæ³ï¼
Emp类添å getDept() æ¹æ³ï¼
// å工类
public class Emp {
...
// åå·¥å±äºæä¸ä¸ªé¨é¨ï¼ä½¿ç¨å¯¹è±¡å½¢å¼è¡¨ç¤º
private Dept dept;
// çædeptçgetæ¹æ³
public Dept getDept() {
return dept;
}
....
ä¿®æ¹xmlé ç½®æ件ï¼
<!-- 级èèµå¼ -->
<bean id="emp" class="com.zzp.spring5.bean.Emp">
<!-- 设置两个æ®éå±æ§ -->
<property name="ename" value="Tom"></property>
<property name="gender" value="ç·"></property>
<!-- 级èèµå¼ -->
<property name="dept" ref="dept"></property>
<property name="dept.dname" value="ææ¯é¨"></property>
</bean>
<bean id="dept" class="com.zzp.spring5.bean.Dept">
<property name="dname" value="è´¢å¡é¨"></property>
</bean>
æ§è¡ï¼testBean3()
[email protected]
Tom::ç·::Dept{dname='ææ¯é¨'}
7ãIOC æä½ Bean 管çï¼xml æ³¨å ¥éåå±æ§ï¼
1ãæ³¨å ¥æ°ç»ç±»åå±æ§
2ãæ³¨å ¥ Listéå
3ãæ³¨å ¥ Mapéå
4ãæ³¨å ¥ Setéå
ï¼1ï¼å建类ãå®ä¹æ°åãlistãmapãsetç±»åå±æ§ï¼å¹¶çæå¯¹åº setæ¹æ³
Stuç±»:
public class Stu {
// 1 æ°ç»ç±»åå±æ§
private String[] courses;
// 2 listéåç±»åå±æ§
List<String> list;
// 3 Mapéåç±»åå±æ§
private Map<String,String> maps;
// 4 setéåç±»åå±æ§
private Set<String> set;
public void setCourses(String[] courses) {
this.courses = courses;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void test(){
System.out.println(Arrays.asList(courses));
System.out.println(list);
System.out.println(maps);
System.out.println(set);
}
}
ï¼2ï¼å¨ Springé ç½®æ件è¿è¡é ç½®
<!--1 éåç±»åå±æ§æ³¨å
¥ -->
<bean id="stu" class="com.zzp.spring5.collectiontype.Stu">
<!-- æ°ç»ç±»åå±æ§æ³¨å
¥ -->
<property name="courses">
<array>
<value>java课ç¨</value>
<value>æ°æ®åºè¯¾ç¨</value>
</array>
</property>
<!-- éåç±»åå±æ§æ³¨å
¥ -->
<property name="list">
<list>
<value>å¼ ä¸</value>
<value>æå</value>
</list>
</property>
<!-- mapç±»åå±æ§æ³¨å
¥ -->
<property name="maps">
<map>
<entry key="JAVA" value="java"></entry>
<entry key="PHP" value="php"></entry>
</map>
</property>
<!-- setç±»åå±æ§æ³¨å
¥ -->
<property name="set">
<set>
<value>MySQL</value>
<value>Redis</value>
</set>
</property>
</bean>
ï¼3ï¼å°æµè¯ï¼
@Test
public void testCollection(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
Stu stu = context.getBean("stu", Stu.class);
System.out.println(stu);
stu.test();
}
æ§è¡ï¼
[email protected]
[java课ç¨, æ°æ®åºè¯¾ç¨]
[å¼ ä¸, æå]
{JAVA=java, PHP=php}
[MySQL, Redis]
5ãå¨éåéé¢è®¾ç½®å¯¹è±¡ç±»åå¼
æ·»å Courseç±»ï¼
public class Course {
// 课ç¨å称
private String cname;
public void setCname(String cname) {
this.cname = cname;
}
@Override
public String toString() {
return "Course{" +
"cname='" + cname + '\'' +
'}';
}
}
æ·»å Stuéå对象ï¼
public class Stu {
....
private List<Course> courseList;
public void setCourseList(List<Course> courseList) {
this.courseList = courseList;
}
....
public void test(){
....
System.out.println(courseList);
}
}
å¨ Springé ç½®æ件è¿è¡é ç½®
<!--1 éåç±»åå±æ§æ³¨å
¥ -->
<bean id="stu" class="com.zzp.spring5.collectiontype.Stu">
.....
<!-- 注å
¥listéåç±»åï¼å¼æ¯å¯¹è±¡ -->
<property name="courseList">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
</bean>
<!-- å建å¤ä¸ªcourse对象 -->
<bean id="course1" class="com.zzp.spring5.collectiontype.Course">
<property name="cname" value="Spring5æ¡æ¶"></property>
</bean>
<bean id="course2" class="com.zzp.spring5.collectiontype.Course">
<property name="cname" value="MyBaticæ¡æ¶"></property>
</bean>
æµè¯æ§è¡ç»æï¼
[email protected]
[java课ç¨, æ°æ®åºè¯¾ç¨]
[å¼ ä¸, æå]
{JAVA=java, PHP=php}
[MySQL, Redis]
[Course{cname='Spring5æ¡æ¶'}, Course{cname='MyBaticæ¡æ¶'}]
6ãæéåæ³¨å ¥é¨åæååºæ¥
ï¼1ï¼å¨ Springé ç½®æ件ä¸å¼å ¥åç§°ç©ºé´ util
xmlns:util=âhttp://www.springframework.org/schema/utilâ
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
![]()
spring5架構一、Spring 架構概述二、IOC容器三、Aop四、JdbTemplate五、事務管理六、Spring5 新特性
ï¼2ï¼ä½¿ç¨ utilæ ç¾å®æ listéåæ³¨å ¥æå
å建Bookç±»ï¼
public class Book {
private List<String> list;
public void setList(List<String> list) {
this.list = list;
}
public void test(){
System.out.println(list);
}
}
å¨ Springé ç½®æ件è¿è¡é ç½®
<!--1 æålistéåç±»åå±æ§æ³¨å
¥ -->
<util:list id="bookList">
<value>æçç»</value>
<value>ä¹é³ç¥å</value>
<value>ä¸é³æ</value>
</util:list>
<!--2 æålistéåç±»åå±æ§æ³¨å
¥ä½¿ç¨ -->
<bean id="book" class="com.zzp.spring5.collectiontype.Book">
<property name="list" ref="bookList"></property>
</bean>
æµè¯åå ï¼
@Test
public void testCollection2(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
Book book = context.getBean("book", Book.class);
System.out.println(book);
book.test();
}
æ§è¡ï¼
[email protected]
[æçç», ä¹é³ç¥å, ä¸é³æ]
8ãIOC æä½ Bean 管çï¼FactoryBeanï¼
1ãSpring æ两ç§ç±»å beanï¼ä¸ç§æ®é beanï¼å¦å¤ä¸ç§ å·¥åbeanï¼FactoryBeanï¼
2ãæ®é beanï¼å¨é ç½®æ件å®ä¹ beanç±»åå°±æ¯è¿åç±»åï¼ä¸é¢æµè¯çæ¡ä¾ xmlé ç½®æ件beanæ ç¾ï¼
3ãå·¥å beanï¼å¨é ç½®æ件å®ä¹ beanç±»åå¯ä»¥åè¿åç±»åä¸ä¸æ ·
ï¼1ï¼ç¬¬ä¸æ¥ å建类ï¼è®©è¿ä¸ªç±»ä½ä¸º å·¥åbeanï¼å®ç°æ¥å£ FactoryBean
ï¼2ï¼ç¬¬äºæ¥ å®ç°æ¥å£éé¢çæ¹æ³ï¼å¨å®ç°çæ¹æ³ä¸å®ä¹è¿åç beanç±»å
å建MyBeanç±»ï¼å®ç°FactoryBeanï¼
public class MyBean implements FactoryBean<Course> {
// å®ä¹è¿åbean
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setCname("abc");
return course;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return FactoryBean.super.isSingleton();
}
}
å¨ Springé ç½®æ件è¿è¡é ç½®
æµè¯åå ï¼
@Test
public void testCollection3(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
Course course = context.getBean("myBean", Course.class);
System.out.println(course);
}
æ§è¡ï¼
Course{cname='abc'}
9ãIOC æä½ Bean 管çï¼beanä½ç¨åï¼
1ãå¨ Springéé¢ï¼è®¾ç½®å建 beanå®ä¾æ¯åå®ä¾è¿æ¯å¤å®ä¾
2ãå¨ Springéé¢ï¼é»è®¤æ åµä¸ï¼beanæ¯åå®ä¾å¯¹è±¡
以Bookç±»ï¼ä½ä¸ºæ¼ç¤ºï¼
æµè¯åå ï¼
@Test
public void testCollection2(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
Book book1 = context.getBean("book", Book.class);
Book book2 = context.getBean("book", Book.class);
System.out.println(book1);
System.out.println(book2);
}
æ§è¡ï¼
[email protected]
[email protected]
两个对象å°åæ¯ä¸è´çï¼è¯´æé»è®¤æ¯åå®ä¾
3ãå¦ä½è®¾ç½®åå®ä¾è¿æ¯å¤å®ä¾
ï¼1ï¼å¨ Springé ç½®æ件 beanæ ç¾éé¢æå±æ§ï¼scopeï¼ç¨äºè®¾ç½®åå®ä¾è¿æ¯å¤å®ä¾
ï¼2ï¼scopeå±æ§å¼ï¼
- 第ä¸ä¸ª é»è®¤å¼ï¼
ï¼è¡¨ç¤ºåå®ä¾å¯¹è±¡singleton
- 第äºä¸ª
ï¼è¡¨ç¤ºæ¯å¤å®ä¾å¯¹è±¡prototype
åå æµè¯ï¼ç»æ
[email protected]
[email protected]
两个对象å°åä¸ä¸æ ·ï¼å¤å®ä¾
ï¼3ï¼
singleton
å
prototype
åºå«
第ä¸
singleton
åå®ä¾ï¼
prototype
å¤å®ä¾
ç¬¬äº è®¾ç½®scopeå¼æ¯
singleton
æ¶åï¼å è½½ springé ç½®æ件æ¶åå°±ä¼å建åå®ä¾å¯¹è±¡ï¼è®¾ç½®scopeå¼æ¯
prototype
æ¶åï¼ä¸æ¯å è½½ springé ç½®æ件æ¶åå建对象ï¼å¨è°ç¨
getBean()
æ¹æ³æ¶åå建å¤å®ä¾å¯¹è±¡
10ãIOC æä½ Bean 管çï¼beançå½å¨æï¼
1ãçå½å¨æ
ï¼1ï¼ä»å¯¹è±¡å建å°å¯¹è±¡éæ¯çè¿ç¨
2ãbeançå½å¨æ
ï¼1ï¼éè¿æé å¨å建 beanå®ä¾ï¼æ åæé ï¼
ï¼2ï¼ä¸º beançå±æ§è®¾ç½®å¼åå ¶ä» beanå¼ç¨ï¼è°ç¨ setæ¹æ³ï¼
ï¼3ï¼è°ç¨ beançåå§åçæ¹æ³ï¼éè¦è¿è¡é ç½®åå§åçæ¹æ³ï¼
ï¼4ï¼beanå¯ä»¥ä½¿ç¨äºï¼å¯¹è±¡è·åå°äºï¼
ï¼5ï¼å½å®¹å¨å ³éçæ¶åï¼è°ç¨ beançéæ¯æ¹æ³ï¼éè¦è¿è¡é ç½®éæ¯çæ¹æ³ï¼
3ãæ¼ç¤º beançå½å¨æ
å建Ordersç±»ï¼
public class Orders {
// æ åæ°æé
public Orders(){
System.out.println("第ä¸æ¥ æ§è¡æ åæ°æé å建beanå®ä¾");
}
private String oname;
public void setOname(String oname) {
this.oname = oname;
System.out.println("第äºæ¥ è°ç¨setæ¹æ³è®¾ç½®å±æ§å¼");
}
// å建æ§è¡çåå§åçæ¹æ³
public void initMethod(){
System.out.println("第ä¸æ¥ æ§è¡åå§åçæ¹æ³");
}
// å建æ§è¡çéæ¯çæ¹æ³
public void destroyMethod(){
System.out.println("第äºæ¥ æ§è¡éæ¯çæ¹æ³");
}
}
å¨ Springé ç½®æ件è¿è¡é ç½®
<bean id="orders" class="com.zzp.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
<property name="oname" value="ææº"></property>
</bean>
åå æµè¯ï¼
@Test
public void testCollection4(){
// ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
Orders orders = context.getBean("orders", Orders.class);
System.out.println("第åæ¥ è·åå建beanå®ä¾å¯¹è±¡");
System.out.println(orders);
// æå¨è®©beanå®ä¾éæ¯
context.close();
}
}
æ§è¡ï¼
第ä¸æ¥ æ§è¡æ åæ°æé å建beanå®ä¾
第äºæ¥ è°ç¨setæ¹æ³è®¾ç½®å±æ§å¼
第ä¸æ¥ æ§è¡åå§åçæ¹æ³
第åæ¥ è·åå建beanå®ä¾å¯¹è±¡
[email protected]
第äºæ¥ æ§è¡éæ¯çæ¹æ³
4ãbean çåç½®å¤çå¨ï¼bean çå½å¨æä¸æ¥
ï¼1ï¼éè¿æé å¨å建 beanå®ä¾ï¼æ åæé ï¼
ï¼2ï¼ä¸º beançå±æ§è®¾ç½®å¼åå ¶ä» beanå¼ç¨ï¼è°ç¨ setæ¹æ³ï¼
ï¼3ï¼æ beanå®ä¾ä¼ é bean åç½®å¤çå¨çæ¹æ³ï¼
postProcessBeforeInitialization()
æ¹æ³ï¼
ï¼4ï¼è°ç¨ beançåå§åçæ¹æ³ï¼éè¦è¿è¡é ç½®åå§åçæ¹æ³ï¼
ï¼5ï¼æ beanå®ä¾ä¼ é bean åç½®å¤çå¨çæ¹æ³ï¼
postProcessAfterInitialization()
æ¹æ³ï¼
ï¼6ï¼beanå¯ä»¥ä½¿ç¨äºï¼å¯¹è±¡è·åå°äºï¼
ï¼7ï¼å½å®¹å¨å ³éçæ¶åï¼è°ç¨ beançéæ¯æ¹æ³ï¼éè¦è¿è¡é ç½®éæ¯çæ¹æ³ï¼
5ãæ¼ç¤ºæ·»å åç½®å¤çå¨ææï¼
ï¼1ï¼å建类ï¼å®ä¾æ¥å£ BeanPostProcessorï¼å建åç½®å¤çå¨
public class MyBeanPost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("å¨åå§åä¹åæ§è¡çæ¹æ³");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("å¨åå§åä¹åæ§è¡çæ¹æ³");
return bean;
}
}
å¨ Springé ç½®æ件è¿è¡æ·»å é ç½®
<bean id="orders" class="com.zzp.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
<property name="oname" value="ææº"></property>
</bean>
<!-- é
ç½®åç½®å¤çå¨ -->
<bean id="myBeanPost" class="com.zzp.spring5.bean.MyBeanPost"></bean>
继ç»ä¸ä¸ä¸ªåå æµè¯ï¼
第ä¸æ¥ æ§è¡æ åæ°æé å建beanå®ä¾
第äºæ¥ è°ç¨setæ¹æ³è®¾ç½®å±æ§å¼
å¨åå§åä¹åæ§è¡çæ¹æ³
第ä¸æ¥ æ§è¡åå§åçæ¹æ³
å¨åå§åä¹åæ§è¡çæ¹æ³
第åæ¥ è·åå建beanå®ä¾å¯¹è±¡
[email protected]
第äºæ¥ æ§è¡éæ¯çæ¹æ³
11ãIOC æä½ Bean 管çï¼xmlèªå¨è£ é ï¼
1ãä»ä¹æ¯èªå¨è£ é
ï¼1ï¼æ ¹æ®æå®è£ é è§åï¼å±æ§å称æè å±æ§ç±»åï¼ï¼Spring èªå¨å°å¹é çå±æ§å¼è¿è¡æ³¨å ¥
2ãæ¼ç¤ºèªå¨è£ é è¿ç¨
å建两个类ï¼
public class Dept {
@Override
public String toString() {
return "Dept{}";
}
}
public class Emp {
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Emp{" +
"dept=" + dept +
'}';
}
public void test(){
System.out.println(dept);
}
}
ï¼1ï¼æ ¹æ®å±æ§å称èªå¨æ³¨å ¥
å¨ Springé ç½®æ件è¿è¡æ·»å é ç½®
<!-- å®ç°èªå¨è£
é
beanæ ç¾å±æ§autowireï¼é
ç½®èªå¨è£
é
autowireå±æ§å¸¸ä¸¤ä¸ªå¼ï¼
byNameæ ¹æ®å±æ§å称注å
¥ï¼æ³¨å
¥å¼beançidå¼åç±»å±æ§å称ä¸æ ·
byTypeæ ¹æ®å±æ§ç±»å注å
¥
-->
<bean id="emp" class="com.zzp.spring5.autowire.Emp" autowire="byName">
<!-- <property name="dept" ref="dept"></property>-->
</bean>
<bean id="dept" class="com.zzp.spring5.autowire.Dept"></bean>
åå æµè¯ï¼
@Test
public void test4(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean5.xml");
Emp emp = context.getBean("emp", Emp.class);
System.out.println(emp);
}
æ§è¡ï¼
Emp{dept=Dept{}}
ï¼2ï¼æ ¹æ®å±æ§ç±»åèªå¨æ³¨å ¥
<!-- å®ç°èªå¨è£
é
beanæ ç¾å±æ§autowireï¼é
ç½®èªå¨è£
é
autowireå±æ§å¸¸ä¸¤ä¸ªå¼ï¼
byNameæ ¹æ®å±æ§å称注å
¥ï¼æ³¨å
¥å¼beançidå¼åç±»å±æ§å称ä¸æ ·
byTypeæ ¹æ®å±æ§ç±»å注å
¥
-->
<bean id="emp" class="com.zzp.spring5.autowire.Emp" autowire="byType">
<!-- <property name="dept" ref="dept"></property>-->
</bean>
<bean id="dept" class="com.zzp.spring5.autowire.Dept"></bean>
æ ¹æ®å±æ§ç±»åèªå¨æ³¨å ¥
byType
ï¼åªè½åªæä¸ä¸ª bean ç±»åçç±» ä¸è½å建两个ï¼å¦ææ两个ï¼åªè½ä½¿ç¨
byName
ã
12ãIOC æä½ Bean 管çï¼å¤é¨å±æ§æ件ï¼
1ãç´æ¥é ç½®æ°æ®åºä¿¡æ¯
ï¼1ï¼é 置德é²ä¼è¿æ¥æ±
ï¼2ï¼å¼å ¥å¾·é²ä¼è¿æ¥æ± ä¾èµ jarå
å¼å ¥ä¾èµ jarå ï¼
å¨ Springé ç½®æ件è¿è¡æ·»å é ç½®
<!--ç´æ¥é
ç½®è¿æ¥æ± -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/userDb"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
2ãå¼å ¥å¤é¨å±æ§æ件é ç½®æ°æ®åºè¿æ¥æ±
ï¼1ï¼å建å¤é¨å±æ§æ件ï¼
properties
æ ¼å¼æ件ï¼åæ°æ®åºä¿¡æ¯
jdbc.properties
æ件å 容å¦ä¸ï¼
prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/userDb
prop.username=root
prop.password=123456
ï¼2ï¼æå¤é¨
properties
å±æ§æ件å¼å ¥å¨ springé ç½®æ件ä¸
â å¼å ¥
context
å称空é´
xmlns:context="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
![]()
spring5架構一、Spring 架構概述二、IOC容器三、Aop四、JdbTemplate五、事務管理六、Spring5 新特性
â¡å¨ springé ç½®æ件使ç¨æ ç¾å¼å ¥å¤é¨å±æ§æ件
<!--å¼å
¥å¤é¨å±æ§æ件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--ç´æ¥é
ç½®è¿æ¥æ± -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${prop.driverClass}"></property>
<property name="url" value="${prop.url}"></property>
<property name="username" value="${prop.username}"></property>
<property name="password" value="${prop.password}"></property>
</bean>
13ãIOC æä½ Bean 管çï¼åºäºæ³¨è§£æ¹å¼ï¼
1ãä»ä¹æ¯æ³¨è§£
ï¼1ï¼æ³¨è§£æ¯ä»£ç ç¹æ®æ è®°ï¼æ ¼å¼ï¼
@注解å称ï¼å±æ§å称=å±æ§å¼ï¼å±æ§å称=å±æ§å¼...ï¼
ï¼2ï¼ä½¿ç¨æ³¨è§£ï¼æ³¨è§£ä½ç¨å¨ç±»ä¸é¢ï¼æ¹æ³ä¸é¢ï¼å±æ§ä¸é¢
ï¼3ï¼ä½¿ç¨æ³¨è§£ç®çï¼ç®å xmlé ç½®
2ãSpring é对Bean 管çä¸å建对象æä¾æ³¨è§£
ï¼1ï¼
@Component
ï¼2ï¼
@Service
ï¼3ï¼
@Controller
ï¼4ï¼
@Repository
*ä¸é¢å个注解åè½æ¯ä¸æ ·çï¼é½å¯ä»¥ç¨æ¥å建 beanå®ä¾
3ãåºäºæ³¨è§£æ¹å¼å®ç°å¯¹è±¡å建
第ä¸æ¥ å¼å ¥ä¾èµ
spring-aop-5.3.6.jar
第äºæ¥ å¼å¯ç»ä»¶æ«æï¼å¼å ¥
context
åç§°ç©ºé´ ä¸é¢ææè¿°ï¼
å¨ Springé ç½®æ件è¿è¡æ·»å é ç½®
<!--å¼å¯ç»ä»¶æ«æ
1 å¦ææ«æå¤ä¸ªå
ï¼å¤ä¸ªå
使ç¨éå·éå¼
2 æ«æå
ä¸å±ç®å½
-->
<context:component-scan base-package="com.zzp.spring5"/>
第ä¸æ¥ å建类ï¼å¨ç±»ä¸é¢æ·»å å建对象注解
import org.springframework.stereotype.Component;
// å¨æ³¨è§£éé¢valueå±æ§å¯ä»¥çç¥ä¸åï¼
// é»è®¤å¼æ¯ç±»åï¼é¦åæ¯å°å ( UserService ==> userService )
@Component(value = "userService") // <bean id="userService" class="..." />ææä¸æ ·
public class UserService {
public void add(){
System.out.println("...UserService.add()....");
}
}
第åæ¥ å°æµè¯
@Test
public void test01(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService);
userService.add();
}
æ§è¡ï¼
[email protected]
...UserService.add()....
è¿é使ç¨å ¶ä»
@Service
ã
@Controller
ã
@Repository
æææ¯ä¸æ ·ç
4ãå¼å¯ç»ä»¶æ«æç»èé ç½®
<!-- å®ä¾1
use-default-filters="false" 表示ç°å¨ä¸ä½¿ç¨é»è®¤filterï¼èªå·±é
ç½®filter
context:include-filter , 设置æ«æåªäºå
容
-->
<context:component-scan base-package="com.zzp.spring5" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- å®ä¾2
ä¸é¢é
ç½®æ«æå
ææå
容
context:exclude-filter , 设置åªäºå
容ä¸è¿è¡æ«æ
-->
<context:component-scan base-package="com.zzp.spring5">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
5ãåºäºæ³¨è§£æ¹å¼å®ç°å±æ§æ³¨å ¥
ï¼1ï¼
@Autowired
ï¼æ ¹æ®å±æ§ç±»åè¿è¡èªå¨è£ é
第ä¸æ¥ æ serviceå dao对象å建ï¼å¨ serviceådao类添å å建对象注解
@Service
public class UserService {
....
}
public interface UserDao {
void add();
}
@Repository
public class UserDaoImpl implements UserDao{
@Override
public void add() {
System.out.println("...UserDao.add()...");
}
}
第äºæ¥ å¨ serviceæ³¨å ¥ dao对象ï¼å¨ service类添å daoç±»åå±æ§ï¼å¨å±æ§ä¸é¢ä½¿ç¨æ³¨è§£
@Autowired
@Service
public class UserService {
//å®ä¹daoç±»åå±æ§
//ä¸éè¦æ·»å setæ¹æ³
//æ·»å 注å
¥å±æ§æ³¨è§£
@Autowired // æ ¹æ®ç±»åè¿è¡æ³¨å
¥
private UserDao userDao;
public void add(){
System.out.println("...UserService.add()....");
userDao.add();
}
}
第ä¸æ¥ å°æµè¯
åå æµè¯
test01()
æ§è¡ç»æï¼
[email protected]
...UserService.add()....
...UserDao.add()...
ï¼2ï¼
@Qualifier
ï¼æ ¹æ®å称è¿è¡æ³¨å ¥
è¿ä¸ª
@Qualifier
注解ç使ç¨ï¼è¦ä¸é¢ç
@Autowired
ä¸èµ·ä½¿ç¨
@Service
public class UserService {
@Autowired // æ ¹æ®ç±»åè¿è¡æ³¨å
¥
@Qualifier(value = "userDaoImpl1") // æ ¹æ®å称è¿è¡æ³¨å
¥
private UserDao userDao;
...
}
@Repository(value = "userDaoImpl1") // é»è®¤ç±»å称 é¦åæ¯å°å
public class UserDaoImpl implements UserDao{
....
}
åå æµè¯ï¼æ§è¡ç»æï¼
[email protected]
...UserService.add()....
...UserDao.add()...
ï¼3ï¼
@Resource
ï¼å¯ä»¥æ ¹æ®ç±»åæ³¨å ¥ï¼ä¹å¯ä»¥æ ¹æ®åç§°æ³¨å ¥
@Service
public class UserService {
//@Resource // æ ¹æ®ç±»åè¿è¡æ³¨å
¥
@Resource(name = "userDaoImpl1") // æ ¹æ®å称è¿è¡æ³¨å
¥
private UserDao userDao;
....
}
åå æµè¯ï¼
[email protected]
...UserService.add()....
...UserDao.add()...
注ï¼
@Resource
注解使ç¨
javax.annotation.Resource
ï¼javaæ©å±å
ï¼4ï¼
@Value
ï¼æ³¨å ¥æ®éç±»åå±æ§
@Service
public class UserService {
@Value(value = "abc")
private String name;
...
public void add(){
System.out.println("...UserService.add()....name:" + name);
userDao.add();
}
}
åå æµè¯ï¼
com.zzp.spring5.service.U[email protected]
...UserService.add()....name:abc
...UserDao.add()...
6ãå®å ¨æ³¨è§£å¼å
ï¼1ï¼å建é 置类ï¼æ¿ä»£ xmlé ç½®
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration // ä½ä¸ºé
置类ï¼æ¿ä»£xmlé
ç½®æ件
@ComponentScan(basePackages = {"com.zzp.spring5"}) // æ«æçå
public class SpringConfig {
}
ï¼2ï¼ç¼åæµè¯ç±»
@Test
public void test02(){
// å è½½é
置类
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService);
userService.add();
}
æ§è¡ï¼
[email protected]
...UserService.add()....name:abc
...UserDao.add()...
ä¸ãAop
1ãAOPï¼æ¦å¿µï¼
1ãä»ä¹æ¯AOP
ï¼1ï¼AOP为
Aspect Oriented Programming
ç缩åï¼æ为ï¼
é¢ååé¢ç¼ç¨ï¼æ¹åï¼
ãAOPæ¯OOPç延ç»ï¼æ¯è½¯ä»¶å¼åä¸çä¸ä¸ªçç¹ï¼ä¹æ¯Springæ¡æ¶ä¸çä¸ä¸ªéè¦å 容ï¼æ¯å½æ°å¼ç¼ç¨çä¸ç§è¡çèåãå©ç¨AOPå¯ä»¥å¯¹ä¸å¡é»è¾çå个é¨åè¿è¡é离ï¼ä»è使å¾ä¸å¡é»è¾åé¨åä¹é´çè¦å度éä½ï¼æé«ç¨åºçå¯éç¨æ§ï¼åæ¶æé«äºå¼åçæçã
ï¼2ï¼éä¿æè¿°ï¼ä¸éè¿ä¿®æ¹æºä»£ç æ¹å¼ï¼å¨ä¸»å¹²åè½éé¢æ·»å æ°åè½
ï¼3ï¼ä½¿ç¨ç»å½ä¾å说æ AOP
2ãAOPï¼åºå±åçï¼
1ãAOP åºå±ä½¿ç¨ å¨æ代ç
ï¼1ï¼æ两ç§æ åµå¨æ代ç
-
第ä¸ç§ ææ¥å£æ åµï¼ä½¿ç¨ JDK å¨æ代ç
å建æ¥å£å®ç°ç±»ä»£ç对象ï¼å¢å¼ºç±»çæ¹æ³
-
第äºç§ 没ææ¥å£æ åµï¼ä½¿ç¨ CGLIB å¨æ代ç
å建åç±»ç代ç对象ï¼å¢å¼ºç±»çæ¹æ³
spring5架構一、Spring 架構概述二、IOC容器三、Aop四、JdbTemplate五、事務管理六、Spring5 新特性
3ãAOPï¼JDK å¨æ代çï¼
1ãä½¿ç¨ JDKå¨æ代çï¼ä½¿ç¨ Proxyç±»éé¢æ¹æ³å建代ç对象
JDK8ææ¡£
ï¼1ï¼è°ç¨
newProxyInstance()
æ¹æ³
æ¹æ³æä¸ä¸ªåæ°ï¼
第ä¸ä¸ªåæ°ï¼
ClassLoader loader
ï¼ï¼ç±»å è½½å¨
第äºä¸ªåæ°ï¼
ç±»<?>[] interfaces
ï¼ï¼å¢å¼ºæ¹æ³æå¨çç±»ï¼è¿ä¸ªç±»å®ç°çæ¥å£ï¼æ¯æå¤ä¸ªæ¥å£
第ä¸ä¸ªåæ°ï¼
InvocationHandler h
ï¼ï¼å®ç°è¿ä¸ªæ¥å£
InvocationHandler
ï¼å建代ç对象ï¼åå¢å¼ºçé¨å
2ãç¼å JDK å¨æ代ç代ç
ï¼1ï¼å建æ¥å£ï¼å®ä¹æ¹æ³
public interface UserDao {
int add(int a,int b);
String update(String id);
}
ï¼2ï¼å建æ¥å£å®ç°ç±»ï¼å®ç°æ¹æ³
public class UserDaoImpl implements UserDao{
@Override
public int add(int a, int b) {
System.out.println("addæ¹æ³æ§è¡äº...");
return a + b;
}
@Override
public String update(String id) {
System.out.println("updateæ¹æ³æ§è¡äº...");
return id;
}
}
ï¼3ï¼ä½¿ç¨ Proxyç±»å建æ¥å£ä»£ç对象
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class JKDProxy {
public static void main(String[] args) {
// å建æ¥å£å®ç°ç±»ä»£ç对象
Class[] interfaces = {UserDao.class};
// // 使ç¨å¿åå
é¨ç±»
// Proxy.newProxyInstance(JKDProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
// @Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// return null;
// }
// });
UserDaoImpl userDao = new UserDaoImpl();
UserDao dao = (UserDao) Proxy.newProxyInstance(JKDProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
int result = dao.add(1,2);
System.out.println("result="+result);
}
}
//å建代ç对象代ç
class UserDaoProxy implements InvocationHandler{
// 1 æå建çæ¯è°ç代ç对象ï¼æè°ä¼ éè¿æ¥
// æåæ°æé ä¼ é
private Object obj;
public UserDaoProxy(Object obj){
this.obj = obj;
}
// å¢å¼ºçé»è¾
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// æ¹æ³ä¹å
System.out.println("æ¹æ³ä¹åæ§è¡..." + method.getName() + " :ä¼ éçåæ°..." + Arrays.asList(args));
// 被å¢å¼ºçæ¹æ³æ§è¡
Object res = method.invoke(obj,args);
// æ¹æ³ä¹å
System.out.println("æ¹æ³ä¹åæ§è¡..." + obj);
return res;
}
}
æ§è¡ï¼
æ¹æ³ä¹åæ§è¡...add :ä¼ éçåæ°...[1, 2]
addæ¹æ³æ§è¡äº...
æ¹æ³ä¹åæ§è¡[email protected]
result=3
4ãAOPï¼æ¯è¯ï¼
1ãè¿æ¥ç¹
ç±»éé¢åªäºæ¹æ³å¯ä»¥è¢«å¢å¼ºï¼è¿äºæ¹æ³ç§°ä¸ºè¿æ¥ç¹
2ãåå ¥ç¹
å®é 被çæ£å¢å¼ºçæ¹æ³ï¼ç§°ä¸ºåå ¥ç¹
3ãéç¥ï¼å¢å¼ºï¼
ï¼1ï¼å®é å¢å¼ºçé»è¾é¨å称为éç¥ ï¼å¢å¼ºï¼
ï¼2ï¼éç¥æå¤ç§ç±»å
- åç½®éç¥
- åç½®éç¥
- ç¯ç»éç¥
- å¼å¸¸éç¥
- æç»éç¥
4ãåé¢
æ¯å¨ä½
ï¼1ï¼æéç¥åºç¨å°åå ¥ç¹è¿ç¨
5ãAOPï¼åå¤ï¼
1ãSpring æ¡æ¶ä¸è¬åºäº AspectJ å®ç° AOP æä½
ï¼1ï¼ä»ä¹æ¯ AspectJ
-
ä¸æ¯ Spring ç»æé¨åï¼ç¬ç« AOP æ¡æ¶ï¼ä¸è¬ AspectJ å Spring æ¡æ¶ä¸èµ·ä½¿ç¨ï¼è¿è¡ AOPæä½AspectJ
2ãåºäº AspectJ å®ç° AOP æä½
ï¼1ï¼åºäº xmlé ç½®æ件å®ç°
ï¼2ï¼åºäºæ³¨è§£æ¹å¼å®ç°ï¼ä½¿ç¨ï¼
3ãå¨é¡¹ç®å·¥ç¨éé¢å¼å ¥ AOP ç¸å ³ä¾èµ
spring-aspects-5.3.6.jar
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
æ¥æ¾ä¾èµå æ¹æ³ï¼
MVNä»åº
å¤å¶å¨é¡¹ç®libç®å½ä¸ï¼
4ãåå ¥ç¹è¡¨è¾¾å¼
ï¼1ï¼åå ¥ç¹è¡¨è¾¾å¼ä½ç¨ï¼ç¥é对åªä¸ªç±»éé¢çåªä¸ªæ¹æ³è¿è¡å¢å¼º
ï¼2ï¼è¯æ³ç»æï¼
-
execution([æé修饰符][è¿åç±»å][ç±»å ¨è·¯å¾][æ¹æ³å称]([åæ°å表]))
ä¸¾ä¾ 1ï¼å¯¹
com.zzp.spring5.dao.BookDao
ç±»éé¢ç
add()
æ¹æ³è¿è¡å¢å¼º
execution(* com.zzp.spring5.dao.BookDao.add(..))
(* 代表ææ)
ä¸¾ä¾ 2ï¼å¯¹
com.zzp.spring5.dao.BookDao
ç±»éé¢çæææ¹æ³è¿è¡å¢å¼º
execution(* com.zzp.spring5.dao.BookDao.*(..))
ä¸¾ä¾ 3ï¼å¯¹
com.zzp.spring5.dao
å éé¢ææç±»ï¼ç±»éé¢çæææ¹æ³è¿è¡å¢å¼º
execution(* com.zzp.spring5.dao.*.*(..))
6ãAOPï¼AspectJ 注解ï¼
1ãå建类ï¼å¨ç±»éé¢å®ä¹æ¹æ³
// 被å¢å¼ºçç±»
public class User {
public void add(){
System.out.println("add.....");
}
}
2ãå建类å¢å¼ºç±»ï¼ç¼åå¢å¼ºé»è¾ï¼
ï¼1ï¼å¨å¢å¼ºç±»éé¢ï¼å建æ¹æ³ï¼è®©ä¸åæ¹æ³ä»£è¡¨ä¸åéç¥ç±»å
// å¢å¼ºçç±»
public class UserProxy {
// åç½®éç¥
public void before(){
System.out.println("before....");
}
}
3ãè¿è¡éç¥é ç½®
ï¼1ï¼å¨ springé ç½®æ件ä¸ï¼å¼å¯æ³¨è§£æ«æ
å¼å
¥ `context`å称空é´
å¼å
¥ `aop`å称空é´
<!-- å¼å¯æ³¨è§£æ«æ -->
<context:component-scan base-package="com.zzp.spring5.aopanno"></context:component-scan>
ï¼2ï¼ä½¿ç¨æ³¨è§£å建 User å UserProxy 对象
æ·»å
@Component
注解
// 被å¢å¼ºçç±»
@Component
public class User {...}
// å¢å¼ºçç±»
@Component
public class UserProxy {...}
ï¼3ï¼å¨å¢å¼ºç±»ä¸é¢æ·»å 注解
@Aspect
import org.aspectj.lang.annotation.Aspect;
// å¢å¼ºçç±»
@Component
@Aspect // çæ代ç对象
public class UserProxy {...}
ï¼4ï¼å¨ springé ç½®æ件ä¸å¼å¯çæ代ç对象
<!-- å¼å¯Aspectçæ代ç对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
4ãé ç½®ä¸åç±»åçéç¥
ï¼1ï¼å¨å¢å¼ºç±»éé¢ï¼å¨ä½ä¸ºéç¥æ¹æ³ä¸é¢æ·»å éç¥ç±»å注解ï¼ä½¿ç¨åå ¥ç¹è¡¨è¾¾å¼é ç½®
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
// å¢å¼ºçç±»
@Component
@Aspect // çæ代ç对象
public class UserProxy {
// åç½®éç¥
// @Before注解表示ä½ä¸ºåç½®éç¥
@Before(value = "execution(* com.zzp.spring5.aopanno.User.add(..))")
public void before(){
System.out.println("before....");
}
}
5ãåå æµè¯
@Test
public void test01(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
User user = context.getBean("user", User.class);
user.add();
}
æ§è¡ï¼
before....
add.....
6ãæµè¯å ¶ä»éç¥ç±»å
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
// å¢å¼ºçç±»
@Component
@Aspect // çæ代ç对象
public class UserProxy {
// åç½®éç¥
// @Before注解表示ä½ä¸ºåç½®éç¥
@Before(value = "execution(* com.zzp.spring5.aopanno.User.add(..))")
public void before(){
System.out.println("before....");
}
// æç»éç¥
@After(value = "execution(* com.zzp.spring5.aopanno.User.add(..))")
public void after(){
System.out.println("after....");
}
// åç½®éç¥ï¼è¿åéç¥ï¼
@AfterReturning(value = "execution(* com.zzp.spring5.aopanno.User.add(..))")
public void afterReturning(){
System.out.println("afterReturning....");
}
// å¼å¸¸éç¥
@AfterThrowing(value = "execution(* com.zzp.spring5.aopanno.User.add(..))")
public void afterThrowing(){
System.out.println("afterThrowing....");
}
// ç¯ç»éç¥
@Around(value = "execution(* com.zzp.spring5.aopanno.User.add(..))")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("ç¯ç»ä¹å....");
//被å¢å¼ºçæ¹æ³æ§è¡
joinPoint.proceed();
System.out.println("ç¯ç»ä¹å....");
}
}
åå æµè¯ï¼
ç¯ç»ä¹å....
before....
add.....
afterReturning....
after....
ç¯ç»ä¹å....
模æå¼å¸¸æ åµï¼
// 被å¢å¼ºçç±»
@Component
public class User {
public void add(){
int i = 10/0;
System.out.println("add.....");
}
}
æ§è¡:
ç¯ç»ä¹å....
before....
afterThrowing....
after....
java.lang.ArithmeticException: / by zero
7ãç¸åçå ¬å ±åå ¥ç¹æ½å
æ·»å
@Pointcut
注解ï¼
// å¢å¼ºçç±»
@Component
@Aspect // çæ代ç对象
public class UserProxy {
// ç¸ååå
¥ç¹æ½å
@Pointcut(value = "execution(* com.zzp.spring5.aopanno.User.add(..))")
public void pointdemo(){
}
// åç½®éç¥
// @Before注解表示ä½ä¸ºåç½®éç¥
@Before(value = "pointdemo()")
public void before(){
System.out.println("before....");
}
....
æµè¯ï¼æ§è¡ç»æ
ç¯ç»ä¹å....
before....
afterThrowing....
after....
8ãæå¤ä¸ªå¢å¼ºç±»å¤ä¸ªåä¸ä¸ªæ¹æ³è¿è¡å¢å¼ºï¼è®¾ç½®å¢å¼ºç±»ä¼å 级
ï¼1ï¼å¨å¢å¼ºç±»ä¸é¢æ·»å 注解 @Order(æ°åç±»å)ï¼æ°åç±»åå¼è¶å°ä¼å 级è¶é«
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Aspect
@Order(1)
public class PersonProxy {
@Before(value = "execution(* com.zzp.spring5.aopanno.User.add(..))")
public void before(){
System.out.println("Person Before....");
}
}
// å¢å¼ºçç±»
@Component
@Aspect // çæ代ç对象
@Order(3)
public class UserProxy {...}
æ§è¡ç»æï¼
Person Before....
ç¯ç»ä¹å....
before....
afterThrowing....
after....
9ãå®å ¨ä½¿ç¨æ³¨è§£å¼å
ï¼1ï¼å建é 置类ï¼ä¸éè¦å建 xmlé ç½®æ件
@Configuration
@ComponentScan(basePackages = {"com.zzp.spring5"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}
ï¼2ï¼æµè¯æ¹æ³ï¼
@Test
public void test03(){
// å è½½é
置类
ApplicationContext context = new AnnotationConfigApplicationContext(ConfigAop.class);
User user = context.getBean("user", User.class);
user.add();
}
æ§è¡ç»æï¼
Person Before....
ç¯ç»ä¹å....
before....
afterThrowing....
after....
7ãAOPï¼AspectJ é ç½®æ件ï¼
1ãå建两个类ï¼å¢å¼ºç±»å被å¢å¼ºç±»ï¼å建æ¹æ³
public class Book {
public void buy(){
System.out.println("buy.....");
}
}
public class BookProxy {
public void before(){
System.out.println("before.....");
}
}
2ãå¨ springé ç½®æ件å建两个类对象
<!-- å建对象 -->
<bean id="book" class="com.zzp.spring5.aopxml.Book"></bean>
<bean id="bookProxy" class="com.zzp.spring5.aopxml.BookProxy"></bean>
3ãå¨ springé ç½®æ件ä¸é ç½®åå ¥ç¹
<!-- é
ç½®aopå¢å¼º -->
<aop:config>
<!-- åå
¥ç¹ -->
<aop:pointcut id="p" expression="execution(* com.zzp.spring5.aopxml.Book.buy(..))"/>
<!-- é
ç½®åé¢ -->
<aop:aspect ref="bookProxy">
<!-- å¢å¼ºä½ç¨å¨å
·ä½çæ¹æ³ä¸ -->
<aop:before method="before" pointcut-ref="p"/>
</aop:aspect>
</aop:config>
æµè¯ï¼
@Test
public void test02(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
Book book = context.getBean("book", Book.class);
book.buy();
}
æ§è¡ç»æ
before.....
buy.....
åãJdbTemplate
1ãJdbcTemplateï¼æ¦å¿µååå¤ï¼
1ãä»ä¹æ¯JdbcTemplate
ï¼1ï¼Springæ¡æ¶å¯¹ JDBC è¿è¡å°è£ ï¼ä½¿ç¨ JdbcTemplate æ¹ä¾¿å®ç°å¯¹æ°æ®åºæä½
2ãåå¤å·¥ä½
ï¼1ï¼å¼å ¥ç¸å ³ jar å
druid-1.1.16.jar
mysql-connector-java-8.0.13.jar
spring-jdbc-5.3.6.jar
spring-tx-5.3.6.jar
spring-orm-5.3.6.jar
ï¼2ï¼å¨ springé ç½®æ件é ç½®æ°æ®åºè¿æ¥æ±
å建å¤é¨å±æ§æ件ï¼
properties
æ ¼å¼æ件ï¼åæ°æ®åºä¿¡æ¯
jdbc.properties
æ件å 容å¦ä¸ï¼
prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/user_db?serverTimezone=GMT%2B8
prop.username=root
prop.password=123456
<!--å¼å
¥å¤é¨å±æ§æ件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--ç´æ¥é
ç½®è¿æ¥æ± -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${prop.driverClass}"></property>
<property name="url" value="${prop.url}"></property>
<property name="username" value="${prop.username}"></property>
<property name="password" value="${prop.password}"></property>
</bean>
ï¼3ï¼é ç½® JdbcTemplate 对象ï¼æ³¨å ¥ DataSource
<!-- JdbcTemplate对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 注å
¥dataSource -->
<property name="dataSource" ref="dataSource"/>
</bean>
ï¼4ï¼å建 serviceç±»ï¼å建daoç±»ï¼å¨ dao æ³¨å ¥ jdbcTemplate 对象
å¼å¯ç»ä»¶æ«æé ç½®ï¼
<!-- ç»ä»¶æ«æ -->
<context:component-scan base-package="com.zzp.spring5"></context:component-scan>
service
@Service
public class BookService {
// 注å
¥dao
@Autowired
private BookDao bookDao;
}
dao
@Repository
public class BookDaoImpl implements BookDao{
//注å
¥JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
}
2ãJdbcTemplate æä½æ°æ®åºï¼æ·»å ï¼
1ãå建æ°æ®åºç表å对åºçå®ä½ç±»
CREATE TABLE `t_book` (
`userid` varchar(32) NOT NULL DEFAULT '' COMMENT 'ç¨æ·id',
`username` varchar(32) NOT NULL DEFAULT '' COMMENT 'ç¨æ·å',
`userstatus` varchar(8) NOT NULL DEFAULT '0' COMMENT 'ç¨æ·ç¶æ'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='ç¨æ·è¡¨';
public class Book{
private String userid;
private String username;
private String userstatus;
get.. set.. æ¹æ³
}
2ãç¼å service å dao
ï¼1ï¼å¨ dao è¿è¡æ°æ®åºæ·»å æä½
@Service
public class BookService {
// 注å
¥dao
@Autowired
private BookDao bookDao;
// æ·»å çæ¹æ³
public void addBook(Book book){
bookDao.add(book);
}
}
public interface BookDao {
// æ·»å çæ¹æ³
void add(Book book);
}
@Repository
public class BookDaoImpl implements BookDao{
//注å
¥JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
// æ·»å çæ¹æ³
@Override
public void add(Book book) {
}
}
ï¼2ï¼è°ç¨ JdbcTemplate 对象éé¢ updateæ¹æ³å®ç°æ·»å æä½
æ两个åæ°ï¼
第ä¸ä¸ªåæ°ï¼
sql
ï¼ï¼sql è¯å¥
第äºä¸ªåæ°ï¼
args
ï¼ï¼å¯ååæ°ï¼è®¾ç½® sql è¯å¥çå¼
@Repository
public class BookDaoImpl implements BookDao{
//注å
¥JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
// æ·»å çæ¹æ³
@Override
public void add(Book book) {
// 1 å建sqlè¯å¥
String sql = "insert into t_book values(?,?,?)";
// 2 è°ç¨æ¹æ³å®ç°
Object[] args = {book.getUserid(),book.getUsername(),book.getUserstatus()};
int update = jdbcTemplate.update(sql,args);
System.out.println("å½±åçè¡æ°ï¼"+update);
}
}
3ãåå æµè¯ï¼
@Test
public void testJdbcTemplate(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService", BookService.class);
Book book = new Book();
book.setUserid("1");
book.setUsername("java");
book.setUserstatus("a");
bookService.addBook(book);
}
ç»æï¼
ä¿¡æ¯: {dataSource-1} inited
å½±åçè¡æ°ï¼1
æ¥çæ°æ®åº
3ãJdbcTemplate æä½æ°æ®åºï¼ä¿®æ¹åå é¤ï¼
@Repository
public class BookDaoImpl implements BookDao{
//注å
¥JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
// æ·»å çæ¹æ³
@Override
public void add(Book book) {
...
}
// 1.ä¿®æ¹
@Override
public void updateBook(Book book) {
String sql = "update t_book set username=?,userstatus=? where userid=?";
Object[] args = {book.getUsername(),book.getUserstatus(),book.getUserid()};
int update = jdbcTemplate.update(sql,args);
System.out.println("ä¿®æ¹çè¡æ°ï¼"+update);
}
// 2.å é¤
@Override
public void deleteBook(String id) {
String sql = "delete from t_book where userid=?";
int update = jdbcTemplate.update(sql,id);
System.out.println("å é¤çè¡æ°ï¼"+update);
}
}
æµè¯ï¼ä¿®æ¹æ¹æ³
@Test
public void testJdbcTemplate(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService", BookService.class);
Book book = new Book();
book.setUserid("1");
book.setUsername("java_update");
book.setUserstatus("a_1");
bookService.updateBook(book);
}
æ§è¡ç»æï¼
ä¿¡æ¯: {dataSource-1} inited
ä¿®æ¹çè¡æ°ï¼1
æ°æ®åºï¼
æµè¯ï¼å é¤æ¹æ³
@Test
public void testJdbcTemplate(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService", BookService.class);
bookService.deleteBook("1");
}
æ§è¡ï¼
ä¿¡æ¯: {dataSource-1} inited
å é¤çè¡æ°ï¼1
æ°æ®åºï¼
4ãJdbcTemplate æä½æ°æ®åºï¼æ¥è¯¢è¿åæ个å¼ï¼
1ãæ¥è¯¢è¡¨éé¢æå¤å°æ¡è®°å½ï¼è¿åæ¯æ个å¼
2ãä½¿ç¨ JdbcTemplate å®ç°æ¥è¯¢è¿åæ个å¼ä»£ç
æ两个åæ°ï¼
第ä¸ä¸ªåæ°ï¼
sql
ï¼ï¼sql è¯å¥
第äºä¸ªåæ°ï¼
requiredType
ï¼ï¼è¿åç±»å Class
@Repository
public class BookDaoImpl implements BookDao{
//注å
¥JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
...
// æ¥è¯¢è¡¨è®°å½æ°
@Override
public int selectCount() {
String sql = "select count(*) from t_book";
Integer count = jdbcTemplate.queryForObject(sql,Integer.class);
return count;
}
}
æµè¯ï¼
@Test
public void testJdbcTemplate(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService", BookService.class);
int count = bookService.findCount();
System.out.println("æ¥è¯¢æ°éï¼" + count);
}
å¨æ°æ®åºæ·»å 2æ¡è®°å½
æ§è¡ç»æï¼
ä¿¡æ¯: {dataSource-1} inited
æ¥è¯¢æ°éï¼2
5ãJdbcTemplate æä½æ°æ®åºï¼æ¥è¯¢è¿å对象ï¼
1ãåºæ¯ï¼æ¥è¯¢å¾ä¹¦è¯¦æ ï¼ä¸ä¸ªå¯¹è±¡å 容ï¼
2ãä½¿ç¨ JdbcTemplate å®ç°æ¥è¯¢è¿å对象
æä¸ä¸ªåæ°
第ä¸ä¸ªåæ°ï¼
sql
ï¼ï¼sql è¯å¥
第äºä¸ªåæ°ï¼
rowMapper
ï¼ï¼RowMapperï¼æ¯æ¥å£ï¼é对è¿åä¸åçç±»åæ°æ®ï¼ä½¿ç¨è¿ä¸ªæ¥å£éé¢å®ç°ç±»å®ææ°æ®å°è£
第ä¸ä¸ªåæ°ï¼
args
ï¼ï¼sql è¯å¥å¼
@Repository
public class BookDaoImpl implements BookDao{
//注å
¥JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
...
// æ¥è¯¢è¿å对象
@Override
public Book findBookInfoById(String id) {
String sql = "select * from t_book where userid=? ";
Book book = jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<Book>(Book.class),id);
return book;
}
}
æµè¯ï¼
Book book = bookService.findOne(â1â);
System.out.println(âæ¥è¯¢æ°æ®ï¼â + book);
æ§è¡ï¼
ä¿¡æ¯: {dataSource-1} inited
æ¥è¯¢æ°æ®ï¼Book{userid='1', username='aa', userstatus='a'}
6ãJdbcTemplate æä½æ°æ®åºï¼æ¥è¯¢è¿åéåï¼
1ãåºæ¯ï¼æ¥è¯¢å¾ä¹¦å表å页
2ãè°ç¨ JdbcTemplate æ¹æ³å®ç°æ¥è¯¢è¿åéå
æä¸ä¸ªåæ°
第ä¸ä¸ªåæ°ï¼
sql
ï¼ï¼sql è¯å¥
第äºä¸ªåæ°ï¼
rowMapper
ï¼ï¼RowMapperï¼æ¯æ¥å£ï¼é对è¿åä¸åçç±»åæ°æ®ï¼ä½¿ç¨è¿ä¸ªæ¥å£éé¢å®ç°ç±»å®ææ°æ®å°è£
第ä¸ä¸ªåæ°ï¼
args
ï¼ï¼sql è¯å¥å¼
@Repository
public class BookDaoImpl implements BookDao{
//注å
¥JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
...
// æ¥è¯¢è¿åéå
@Override
public List<Book> findAllBook() {
String sql = "select * from t_book ";
// è°ç¨æ¹æ³
List<Book> bookList = jdbcTemplate.query(sql,new BeanPropertyRowMapper<Book>(Book.class));
return bookList;
}
}
æµè¯ï¼
List<Book> all = bookService.findAll();
System.out.println(âæ¥è¯¢éåï¼â + all);
æ§è¡ï¼
ä¿¡æ¯: {dataSource-1} inited
æ¥è¯¢éåï¼[Book{userid='1', username='aa', userstatus='a'}, Book{userid='', username='', userstatus='0b'}]
7ãJdbcTemplate æä½æ°æ®åºï¼æ¹éæä½ï¼
1ãæ¹éæä½ï¼æä½è¡¨éé¢å¤æ¡è®°å½
2.ãJdbcTemplate å®ç°æ¹éæ·»å æä½
æ两个åæ°ï¼
第ä¸ä¸ªåæ°ï¼
sql
ï¼ï¼sql è¯å¥
第äºä¸ªåæ°ï¼
batchArgs
ï¼ï¼Listéåï¼æ·»å å¤æ¡è®°å½æ°æ®
@Repository
public class BookDaoImpl implements BookDao{
//注å
¥JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
...
// æ¹éæ·»å
@Override
public void batchAdd(List<Object[]> batchArgs) {
String sql = "insert into t_book values (?,?,?) ";
int[] ints = jdbcTemplate.batchUpdate(sql,batchArgs);
System.out.println("æ¹éæ·»å ï¼"+ Arrays.toString(ints));
}
}
æµè¯ï¼
List<Object[]> batchArgs = new ArrayList<>();
Object[] arg1 = {â3â,âjavaâ,âaâ};
Object[] arg2 = {â4â,âc++â,âbâ};
Object[] arg3 = {â5â,âMySQLâ,âcâ};
batchArgs.add(arg1);
batchArgs.add(arg2);
batchArgs.add(arg3);
bookService.batchAdd(batchArgs);
æ§è¡ï¼
ä¿¡æ¯: {dataSource-1} inited
æ¹éæ·»å ï¼[1, 1, 1]
æ°æ®åºï¼
3.ãJdbcTemplate å®ç°æ¹éä¿®æ¹æä½
@Repository
public class BookDaoImpl implements BookDao{
//注å
¥JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
...
// æ¹éä¿®æ¹
@Override
public void batchUpate(List<Object[]> batchArgs) {
String sql = "update t_book set username=?,userstatus=? where userid=?";
int[] ints = jdbcTemplate.batchUpdate(sql,batchArgs);
System.out.println("æ¹éä¿®æ¹ï¼"+ Arrays.toString(ints));
}
}
æµè¯ï¼
List<Object[]> batchArgs = new ArrayList<>();
Object[] arg1 = {âjava_updateâ,âa_uâ,â3â};
Object[] arg2 = {âc++_updateâ,âb_uâ,â4â};
Object[] arg3 = {âMySQL_updateâ,âc_uâ,â5â};
batchArgs.add(arg1);
batchArgs.add(arg2);
batchArgs.add(arg3);
bookService.batchUpdate(batchArgs);
æ§è¡ï¼
ä¿¡æ¯: {dataSource-1} inited
æ¹éä¿®æ¹ï¼[1, 1, 1]
æ°æ®åºï¼
4.ãJdbcTemplate å®ç°æ¹éå é¤æä½
@Repository
public class BookDaoImpl implements BookDao{
//注å
¥JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
...
// æ¹éå é¤
@Override
public void batchDelete(List<Object[]> batchArgs) {
String sql = "delete from t_book where userid=? ";
int[] ints = jdbcTemplate.batchUpdate(sql,batchArgs);
System.out.println("æ¹éå é¤ï¼"+ Arrays.toString(ints));
}
}
æµè¯ï¼
List<Object[]> batchArgs = new ArrayList<>();
Object[] arg1 = {â3â};
Object[] arg2 = {â4â};
batchArgs.add(arg1);
batchArgs.add(arg2);
bookService.batchDelete(batchArgs);
æ§è¡ï¼
ä¿¡æ¯: {dataSource-1} inited
æ¹éå é¤ï¼[1, 1]
æ°æ®åºï¼
äºãäºå¡ç®¡ç
1ãäºå¡æä½ï¼äºå¡æ¦å¿µï¼
1ãä»ä¹æ¯äºå¡
ï¼1ï¼äºå¡æ¯æ°æ®åºæä½æåºæ¬åå ï¼é»è¾ä¸ä¸ç»æä½ï¼è¦ä¹é½æåï¼å¦ææä¸ä¸ªå¤±è´¥æææä½é½å¤±è´¥
ï¼2ï¼å ¸ååºæ¯ï¼é¶è¡è½¬è´¦
å°æ 转账 100 ç» å°ç
å°æ å° 100 ï¼å°ç å¤ 100
2ãäºå¡å个ç¹æ§ï¼ACIDï¼
ï¼1ï¼ååæ§
ï¼2ï¼ä¸è´æ§
ï¼3ï¼é离æ§
ï¼4ï¼æä¹ æ§
2ãäºå¡æä½ï¼æ建äºå¡æä½ç¯å¢ï¼
ç®åçç解å¾ï¼
1ãå建æ°æ®åºï¼æ·»å è®°å½
CREATE TABLE `t_account` (
`id` varchar(32) NOT NULL DEFAULT '' COMMENT 'ç¨æ·id',
`username` varchar(32) NOT NULL DEFAULT '' COMMENT 'ç¨æ·å',
`money` int(8) NOT NULL DEFAULT 0 COMMENT 'éé¢'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='è´¦å·è¡¨';
INSERT INTO t_account (id,username,money) VALUES("1","å°æ",1000);
INSERT INTO t_account (id,username,money) VALUES("2","å°ç",1000);
2ãå建 serviceï¼æ建 daoï¼å®æ对象å建åæ³¨å ¥å ³ç³»
ï¼1ï¼service æ³¨å ¥daoï¼å¨daoæ³¨å ¥ JdbcTemplateï¼å¨ JdbcTemplate æ³¨å ¥ DataSource
JdbcTemplate æ³¨å ¥ DataSource å¤ç¨ä¸é¢çå®ä¾ï¼
public interface UserDao {
}
@Repository
public class UserDaoImpl implements UserDao{
@Autowired
private JdbcTemplate jdbcTemplate;
}
@Service
public class UserService {
//注å
¥dao
@Autowired
private UserDao userDao;
}
3ãå¨daoå建两个æ¹æ³ï¼å¤é±åå°é±çæ¹æ³ï¼å¨ serviceå建æ¹æ³ï¼è½¬è´¦çæ¹æ³ï¼
public interface UserDao {
//å¤é±
void addMoney();
//å°é±
void reduceMoeny();
}
@Repository
public class UserDaoImpl implements UserDao{
@Autowired
private JdbcTemplate jdbcTemplate;
// å°æ 转账 100 ç» å°ç
//å°é±
@Override
public void reduceMoeny() {
String sql = "update t_account set money= money-? where username=?";
jdbcTemplate.update(sql,100,"å°æ");
}
//å¤é±
@Override
public void addMoney() {
String sql = "update t_account set money= money+? where username=?";
jdbcTemplate.update(sql,100,"å°ç");
}
}
@Service
public class UserService {
//注å
¥dao
@Autowired
private UserDao userDao;
//转账çæ¹æ³
public void accountMoney(){
//å°æå°100
userDao.reduceMoeny();
//å°çå¤100
userDao.addMoney();
}
}
æµè¯ï¼
@Test
public void testAccount(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.accountMoney();
}
æ§è¡ï¼
4ãä¸é¢ä»£ç ï¼å¦ææ£å¸¸æ§è¡æ²¡æé®é¢çï¼ä½æ¯å¦æ代ç æ§è¡è¿ç¨ä¸åºç°å¼å¸¸ï¼å°±æé®é¢
//转账çæ¹æ³
public void accountMoney(){
//å°æå°100
userDao.reduceMoeny();
//模æå¼å¸¸
int i= 10/0;
//å°çå¤100
userDao.addMoney();
}
å¨æéé¢è¿åï¼
æ§è¡ï¼
ä¿¡æ¯: {dataSource-1} inited
java.lang.ArithmeticException: / by zero
æ°æ®åºï¼
ï¼1ï¼ä¸é¢é®é¢å¦ä½è§£å³å¢ï¼
使ç¨äºå¡è¿è¡è§£å³
ï¼2ï¼äºå¡æä½è¿ç¨
//转账çæ¹æ³
public void accountMoney(){
try {
// 第ä¸æ¥ å¼å¯äºå¡
// 第äºæ¥ è¿è¡ä¸å¡æä½
//å°æå°100
userDao.reduceMoeny();
//模æå¼å¸¸
int i= 10/0;
//å°çå¤100
userDao.addMoney();
// 第ä¸æ¥ 没æåéå¼å¸¸ï¼æ交äºå¡
}catch (Exception e){
// 第åæ¥ åºç°å¼å¸¸ï¼äºå¡åæ»
}
}
3ãäºå¡æä½ï¼Spring äºå¡ç®¡çä»ç»ï¼
1ãäºå¡æ·»å å° JavaEE ä¸å±ç»æéé¢ Service å±ï¼ä¸å¡é»è¾å±ï¼
2ãå¨ Spring è¿è¡äºå¡ç®¡çæä½
ï¼1ï¼æ两ç§æ¹å¼ï¼ç¼ç¨å¼äºå¡ç®¡ç å 声æå¼äºå¡ç®¡çï¼ä½¿ç¨ï¼
3ã声æå¼äºå¡ç®¡ç
ï¼1ï¼åºäºæ³¨è§£æ¹å¼ï¼ä½¿ç¨ï¼
ï¼2ï¼åºäº xml é ç½®æ件æ¹å¼
4ãå¨ Spring è¿è¡å£°æå¼äºå¡ç®¡çï¼åºå±ä½¿ç¨ AOP åç
5ãSpring äºå¡ç®¡ç API
ï¼1ï¼éè¿ä¸ä¸ªæ¥å£ï¼ä»£è¡¨äºå¡ç®¡çå¨ï¼è¿ä¸ªæ¥å£é对ä¸åçæ¡æ¶æä¾ä¸åçå®ç°ç±»
PlatformTransactionManager
æ¥å£ï¼äºå¡ç®¡çå¨ï¼
4ãäºå¡æä½ï¼æ³¨è§£å£°æå¼äºå¡ç®¡çï¼
1ãå¨ spring é ç½®æ件é ç½®äºå¡ç®¡çå¨
<!-- å建äºå¡ç®¡çå¨ -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注å
¥æ°æ®æº -->
<property name="dataSource" ref="dataSource"/>
</bean>
2ãå¨ spring é ç½®æ件ï¼å¼å¯äºå¡æ³¨è§£
ï¼1ï¼å¨ spring é ç½®æ件å¼å ¥å称空é´
tx
xmlns:tx="http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
ï¼2ï¼å¼å¯äºå¡æ³¨è§£
<!-- å¼å¯äºå¡æ³¨è§£ -->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
3ãå¨ serviceå±ç±»ä¸é¢ï¼è·åserviceç±»éé¢æ¹æ³ä¸é¢ï¼æ·»å äºå¡æ³¨è§£
ï¼1ï¼
@Transactional
ï¼è¿ä¸ªæ³¨è§£æ·»å å°ç±»ä¸é¢ï¼ä¹å¯ä»¥æ·»å æ¹æ³ä¸é¢
ï¼2ï¼å¦ææè¿ä¸ªæ³¨è§£æ·»å ç±»ä¸é¢ï¼è¿ä¸ªç±»éé¢ææçæ¹æ³é½æ·»å äºäºå¡
ï¼3ï¼å¦ææè¿ä¸ªæ³¨è§£æ·»å æ¹æ³ä¸é¢ï¼ä¸ºè¿ä¸ªæ¹æ³æ·»å äºå¡
@Service
@Transactional
public class UserService {...}
æµè¯ï¼å ææ°æ®è¿åå为1000
æ§è¡ï¼
ä¿¡æ¯: {dataSource-1} inited
java.lang.ArithmeticException: / by zero
æ°æ®åºï¼
5ãäºå¡æä½ï¼å£°æå¼äºå¡ç®¡çåæ°é ç½®ï¼
1ãå¨ serviceç±»ä¸æ·»å 注解
@Transactional
ï¼å¨è¿ä¸ªæ³¨è§£éé¢å¯ä»¥é ç½®äºå¡ç¸å ³åæ°å±æ§
2ã
propagation
ï¼äºå¡ä¼ æè¡ä¸º
ï¼1ï¼å¤äºå¡æ¹æ³ç´æ¥è¿è¡è°ç¨ï¼è¿ä¸ªè¿ç¨ä¸äºå¡æ¯å¦ä½è¿è¡ç®¡çç
äºå¡çä¼ æè¡ä¸ºå¯ä»¥æä¼ æå±æ§æå®ãSpring å®ä¹äº 7 ç§ç±»åä¼ æè¡ä¸ºï¼
ä¼ æå±æ§ | æè¿° |
---|---|
REQUIRED | å¦ææäºå¡å¨è¿è¡ï¼å½åçæ¹æ³å°±å¨è¿ä¸ªäºå¡å è¿è¡ï¼å¦åï¼å°±å¯å¨ä¸ä¸ªæ°çäºå¡ï¼å¹¶å¨èªå·±çäºå¡å è¿è¡ |
REQUIRED_NEW | å½åçæ¹æ³å¿ é¡»å¯å¨æ°äºå¡ï¼å¹¶å¨å®èªå·±çäºå¡å è¿è¡ï¼å¦ææäºå¡æ£å¨è¿è¡ï¼åºè¯¥å°å®æèµ· |
SUPPORTS | å¦ææäºå¡å¨è¿è¡ï¼å½åçæ¹æ³å°±å¨è¿ä¸ªäºå¡å ï¼å¦åå®å¯ä»¥ä¸è¿è¡å¨äºå¡ä¸ |
NOT_SUPPORTED | å½åçæ¹æ³ä¸åºè¯¥è¿è¡å¨äºå¡ä¸ï¼å¦ææè¿è¡çäºå¡ï¼å°å®æèµ· |
MANDATORY | å½åçæ¹æ³å¿ é¡»è¿è¡å¨äºå¡å ï¼å¦æ没ææ£å¨è¿è¡çäºå¡ï¼å°±æåºå¼å¸¸ |
NEVER | å½åçæ¹æ³ä¸åºè¯¥è¿è¡å¨äºå¡ä¸ï¼å¦ææè¿è¡çäºå¡ï¼å°±æåºå¼å¸¸ |
NESTED | å¦ææäºå¡å¨è¿è¡ï¼å½åçæ¹æ³å°±åºè¯¥å¨è¿ä¸ªäºå¡çåµå¥äºå¡å è¿è¡ãå¦åï¼å°±å¯å¨ä¸ä¸ªæ°çäºå¡ï¼å¹¶å¨å®èªå·±çäºå¡å è¿è¡ã |
é ç½®æ¹å¼ï¼
propagation = Propagation.REQUIRED
é»è®¤æ¯
REQUIRED
ï¼
@Service
@Transactional(propagation = Propagation.REQUIRED)
public class UserService {...}
3ã
isolation
ï¼äºå¡é离级å«
ï¼1ï¼äºå¡æç¹æ§æ为é离æ§ï¼å¤äºå¡æä½ä¹é´ä¸ä¼äº§çå½±åãä¸èèé离æ§ä¼äº§çå¾å¤é®é¢
ï¼2ï¼æä¸ä¸ªè¯»é®é¢ï¼è读ãä¸å¯éå¤è¯»ãèï¼å¹»ï¼è¯»
ï¼3ï¼è读ï¼ä¸ä¸ªæªæ交äºå¡è¯»åå°å¦ä¸ä¸ªæªæ交äºå¡çæ°æ®
ï¼4ï¼ä¸å¯éå¤è¯»ï¼ä¸ä¸ªæªæ交äºå¡è¯»åå°å¦ä¸ä¸ªæ交äºå¡ä¿®æ¹çæ°æ®
ï¼5ï¼èï¼å¹»ï¼è¯»ï¼ä¸ä¸ªæªæ交äºå¡è¯»åå°å¦ä¸ä¸ªäºå¡æ·»å çæ°æ®
ï¼6ï¼è§£å³ï¼éè¿è®¾ç½®äºå¡é离级å«ï¼è§£å³è¯»é®é¢
è读 | ä¸å¯éå¤è¯» | 幻读 | |
---|---|---|---|
READ UNCOMMITTED (读æªæ交) | æ | æ | æ |
READ COMMITTED (读已æ交) | æ | æ | æ |
REPEATABLE READ (å¯éå¤è¯») | æ | æ | æ |
SERIALIZABLE (串è¡å) | æ | æ | æ |
é ç½®æ¹å¼ï¼
isolation = Isolation.REPEATABLE_READ
@Service
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
public class UserService {...}
4ã
timeout
ï¼è¶ æ¶æ¶é´
ï¼1ï¼äºå¡éè¦å¨ä¸å®æ¶é´å è¿è¡æ交ï¼å¦æä¸æ交åè¿è¡åæ»
ï¼2ï¼é»è®¤å¼æ¯ -1ï¼æ²¡ææ¶é´éå¶è¶ æ¶ï¼ï¼è®¾ç½®æ¶é´ä»¥ç§åä½è¿è¡è®¡ç®
é ç½®æ¹å¼ï¼
timeout = 1
@Service
@Transactional(timeout = 1,propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
public class UserService {...}
5ã
readOnly
ï¼æ¯å¦åªè¯»
ï¼1ï¼è¯»ï¼æ¥æ¾æä½ï¼åï¼æ·»å ä¿®æ¹å é¤æä½
ï¼2ï¼readOnly é»è®¤å¼ falseï¼è¡¨ç¤ºå¯ä»¥æ¥è¯¢ï¼å¯ä»¥æ·»å ä¿®æ¹å é¤æä½
ï¼3ï¼è®¾ç½® readOnly å¼æ¯ trueï¼è®¾ç½®æ true ä¹åï¼åªè½æ¥è¯¢
é ç½®æ¹å¼ï¼
readOnly = false
@Service
@Service
@Transactional(readOnly = false,timeout = 1,propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
public class UserService {...}
6ã
rollbackFor
ï¼åæ»
ï¼1ï¼è®¾ç½®åºç°åªäºå¼å¸¸è¿è¡äºå¡åæ»
7ã
noRollbackFor
ï¼ä¸åæ»
ï¼1ï¼è®¾ç½®åºç°åªäºå¼å¸¸ä¸è¿è¡äºå¡åæ»
6ãäºå¡æä½ï¼XML 声æå¼äºå¡ç®¡çï¼
1ãå¨ spring é ç½®æ件ä¸è¿è¡é ç½®
第ä¸æ¥ é ç½®äºå¡ç®¡çå¨
第äºæ¥ é ç½®éç¥
第ä¸æ¥ é ç½®åå ¥ç¹ååé¢
<!-- ç»ä»¶æ«æ -->
<context:component-scan base-package="com.zzp.spring5"></context:component-scan>
<!--å¼å
¥å¤é¨å±æ§æ件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--ç´æ¥é
ç½®è¿æ¥æ± -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${prop.driverClass}"></property>
<property name="url" value="${prop.url}"></property>
<property name="username" value="${prop.username}"></property>
<property name="password" value="${prop.password}"></property>
</bean>
<!-- JdbcTemplate对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 注å
¥dataSource -->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 1 å建äºå¡ç®¡çå¨ -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注å
¥æ°æ®æº -->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 2 é
ç½®éç¥ -->
<tx:advice id="txadvice">
<!-- é
ç½®äºå¡åæ° -->
<tx:attributes>
<!-- æå®åªç§è§åçæ¹æ³ä¸é¢æ·»å äºå¡ -->
<tx:method name="accountMoney" propagation="REQUIRED" isolation="REPEATABLE_READ"/>
<!-- <tx:method name="account*"/> *ï¼éé
符-->
</tx:attributes>
</tx:advice>
<!-- 3 é
ç½®åå
¥ç¹ååé¢ -->
<aop:config>
<!-- é
ç½®åå
¥ç¹ -->
<aop:pointcut id="pt" expression="execution(* com.zzp.spring5.service.UserService.*(..))"/>
<!-- é
ç½®åé¢ -->
<aop:advisor advice-ref="txadvice" pointcut-ref="pt"></aop:advisor>
</aop:config>
åå æµè¯ï¼
@Test
public void testAccount2(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.accountMoney();
}
æ§è¡ï¼
ä¿¡æ¯: {dataSource-1} inited
java.lang.ArithmeticException: / by zero
at com.zzp.spring5.service.UserService.accountMoney(UserService.java:32)
æ°æ®åºæ ååï¼
7ãäºå¡æä½ï¼å®å ¨æ³¨è§£å¼åï¼
1ãå建é 置类ï¼ä½¿ç¨é 置类æ¿ä»£ xmlé ç½®æ件
@Configuration //é
置类
@ComponentScan(basePackages = {"com.zzp.spring5"})
@EnableTransactionManagement //å¼å¯äºå¡
public class TxConfig {
//å建æ°æ®åºçè¿æ¥æ±
@Bean
public DruidDataSource getDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/user_db?serverTimezone=GMT%2B8");
dataSource.setUsername("root");
dataSource.setPassword("123456");
return dataSource;
}
//å建JdbcTemlplate对象
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource){
// å°ioc容å¨ä¸æ ¹æ®ç±»åæ¾å°dataSource
JdbcTemplate jdbcTemplate = new JdbcTemplate();
//注å
¥dataSource
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
//å建äºå¡ç®¡çå¨
@Bean
public DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}
æµè¯ï¼
@Test
public void testAccount3(){
ApplicationContext context = new AnnotationConfigApplicationContext(TxConfig.class);
UserService userService = context.getBean("userService", UserService.class);
userService.accountMoney();
}
æ§è¡ï¼
ä¿¡æ¯: {dataSource-1} inited
java.lang.ArithmeticException: / by zero
at com.zzp.spring5.service.UserService.accountMoney(UserService.java:32)
å ãSpring5 æ°ç¹æ§
Spring Framework 5 ä¸æææ¡£
1ãSpring5 æ¡æ¶æ°åè½
1ãéè¿ä½¿ç¨æ³åçç¹æ§æé«å¯è¯»æ§
2ãæ´ä¸ª Spring æ¡æ¶æ代ç åºäº Java8ï¼è¿è¡æ¶å ¼å®¹ JDK9ï¼è®¸å¤ä¸å»ºè®®ä½¿ç¨çç±»åæ¹æ³å¨ä»£ç åºä¸å é¤
3ãSpring 5.0æ¡æ¶èªå¸¦äºéç¨çæ¥å¿å°è£
ï¼1ï¼Spring5 已移é¤äº Log4jConfigListenerï¼å®æ¹å»ºè®®ä½¿ç¨ Log4j2
ï¼2ï¼Spring5 æ¡æ¶æ´å Log4j2
第ä¸æ¥ å¼å ¥jarå
å¼å ¥é¡¹ç®ä¸
第äºæ¥ å建 log4j2.xml é ç½®æ件
<?xml version="1.0" encoding="UTF-8"?>
<!-- æ¥è®°çº§å«ä»¥åä¼å
级æåºï¼ OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!-- Configurationåé¢çstatusç¨äºè®¾ç½®log4j2èªèº«å
é¨çä¿¡æ¯è¾åºï¼å¯ä»¥ä¸è®¾ç½®ï¼
å½è®¾ç½®ætraceæ¶ï¼å¯ä»¥çå°log4j2å
é¨åç§è¯¦ç»è¾åº -->
<Configuration status="INFO">
<!-- å
å®ä¹ææçappender -->
<appenders>
<!-- è¾åºæ¥å¿ä¿¡æ¯å°æ§å¶å° -->
<console name="Console" target="SYSTEM_OUT">
<!-- æ§å¶æ¥å¿è¾åºæ ¼å¼ -->
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</console>
</appenders>
<!-- ç¶åå®ä¹loggerï¼åªæå®ä¹äºlogger并å¼å
¥çappenderï¼appenderæä¼çæ -->
<!-- root: ç¨æ¥æå®é¡¹ç®çæ ¹æ¥å¿ï¼å¦æ没æåç¬æå®Loggerï¼åä¼ä½¿ç¨rootä½ä¸ºé»è®¤çæ¥å¿è¾åº -->
<loggers>
<root level="info">
<appender-ref ref="Console"/>
</root>
</loggers>
</Configuration>
æµè¯ï¼è¿è¡ä¸é¢ä½¿ç¨ç
testAccount3()
æ¹æ³
è¿è¡ç»æï¼
å åæ¯ INFO 级å«æ¥å¿è¾åº ç°å¨æ¹æ DEBUG æ¥è®°çº§å«è¾åº
æµè¯è¾åºï¼æ´å¤çæ¥è®°è¾åº
æå¨å¨æ§å¶å°æ¥å¿è¾åºï¼
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UserLog {
private static final Logger log = LoggerFactory.getLogger(UserLog.class);
public static void main(String[] args) {
log.info("hello log4j2");
log.warn("hello log4j2");
}
}
æ§è¡ç»æï¼æ§å¶å°è¾åºï¼
4ãSpring5 æ¡æ¶æ ¸å¿å®¹å¨æ¯æ@Nullable注解
ï¼1ï¼
@Nullable
注解å¯ä»¥ä½¿ç¨å¨æ¹æ³ä¸é¢ï¼å±æ§ä¸é¢ï¼åæ°ä¸é¢ï¼è¡¨ç¤ºæ¹æ³è¿åå¯ä»¥ä¸ºç©ºï¼å±æ§å¼å¯ä»¥ä¸ºç©ºï¼åæ°å¼å¯ä»¥ä¸ºç©º
ï¼2ï¼æ³¨è§£ç¨å¨æ¹æ³ä¸é¢ï¼æ¹æ³è¿åå¼å¯ä»¥ä¸ºç©º
ï¼3ï¼æ³¨è§£ä½¿ç¨å¨æ¹æ³åæ°éé¢ï¼æ¹æ³åæ°å¯ä»¥ä¸ºç©º
ï¼4ï¼æ³¨è§£ä½¿ç¨å¨å±æ§ä¸é¢ï¼å±æ§å¼å¯ä»¥ä¸ºç©º
5ãSpring5 æ ¸å¿å®¹å¨å½æ°å¼é£æ ¼GenericApplicationContext
å建Userç±»:
public class User {
};
åå æµè¯ï¼
// å½æ°å¼é£æ ¼å建对象ï¼äº¤ç»springè¿è¡ç®¡ç
@Test
public void testGenericApplicationContext(){
// 1 å建 GenericApplicationContext对象
GenericApplicationContext context = new GenericApplicationContext();
// 2 è°ç¨contextçæ¹æ³å¯¹è±¡æ³¨å
context.refresh();
context.registerBean("user1",User.class,() -> new User() );
// 3 è·åå¨spring注åç对象
// User user = (User)context.getBean("com.zzp.spring5.test.User"); // context.registerBean(User.class,() -> new User() ); ä¸æå® beanName
User user = (User)context.getBean("user1");
System.out.println(user);
}
æ§è¡ï¼
[email protected]
6ãSpring5 æ¯ææ´å JUnit5
ï¼1ï¼æ´å JUnit4
第ä¸æ¥ å¼å ¥ Spring ç¸å ³é对æµè¯ä¾èµ
spring-test-5.3.6.jar
第äºæ¥ å建æµè¯ç±» ï¼ä½¿ç¨æ³¨è§£æ¹å¼å®æ
使ç¨
org.junit.Test
å
import com.zzp.spring5.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class) // æå®åå
æµè¯æ¡æ¶junit4
@ContextConfiguration("classpath:bean1.xml") // å è½½é
ç½®æ件
public class JTest4 {
@Autowired
private UserService userService;
@Test
public void test1(){
userService.accountMoney();
}
}
æ§è¡ï¼
ï¼2ï¼Spring5 æ´å JUnit5
第ä¸æ¥ å¼å ¥ JUnit5 ç jar å
第äºæ¥ å建æµè¯ç±»ï¼ä½¿ç¨æ³¨è§£å®æ
使ç¨
org.junit.jupiter.api.Test
å
import com.zzp.spring5.service.UserService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ExtendWith(SpringExtension.class)
@ContextConfiguration("classpath:bean1.xml")
public class JTest5 {
@Autowired
private UserService userService;
@Test
public void test1(){
userService.accountMoney();
}
}
æ§è¡ï¼
ï¼3ï¼ä½¿ç¨ä¸ä¸ªå¤å注解æ¿ä»£ä¸é¢ä¸¤ä¸ªæ³¨è§£å®ææ´åï¼
@SpringJunitConfig
//@ExtendWith(SpringExtension.class)
//@ContextConfiguration("classpath:bean1.xml")
@SpringJUnitConfig(locations = "classpath:bean1.xml")
public class JTest5 {...}
æ§è¡æææ¯åä¸é¢ä¸æ ·ç
2ãSpring5 æ¡æ¶æ°åè½ï¼Webfluxï¼
1ãSpringWebfluxä»ç»
å®æ¹ææ¡£ Spring WebFlux
ï¼1ï¼æ¯ Spring5 æ·»å æ°ç模åï¼ç¨äº web å¼åçï¼åè½ SpringMVC 类似çï¼Webflux 使ç¨å½åä¸ç§æ¯è¾æµè¡çååºå¼ç¼ç¨åºç°çæ¡æ¶
ï¼2ï¼ä½¿ç¨ä¼ ç» web æ¡æ¶ï¼æ¯å¦ SpringMVC ï¼è¿äºåºäº Servlet 容å¨ï¼Webflux æ¯ä¸ç§å¼æ¥éé»å¡çæ¡æ¶ï¼å¼æ¥éé»å¡çæ¡æ¶å¨ Servlet3.1 以åææ¯æçï¼æ ¸å¿æ¯åºäº Reactorï¼ååºå¼ç¼ç¨ï¼ çç¸å ³ API å®ç°çã
ï¼3ï¼è§£éä»ä¹æ¯å¼æ¥éé»å¡
å¼æ¥åæ¥
éé»å¡åé»å¡
--ä¸é¢é½æ¯é对对象ä¸ä¸æ ·
å¼æ¥åæ¥é对è°ç¨è
ï¼è°ç¨è
åé请æ±ï¼
å¦æçç对æ¹ååºä¹åæå»åå
¶ä»äºæ
å°±æ¯åæ¥
å¦æåé请æ±ä¹åä¸çç对æ¹ååºå°±å»åå
¶ä»äºæ
å°±æ¯å¼æ¥
--
é»å¡åéé»å¡é对被è°ç¨è
ï¼è¢«è°ç¨è
æ¶å°è¯·æ±ä¹åï¼
åå®è¯·æ±ä»»å¡ä¹åæç»åºåé¦å°±æ¯é»å¡ï¼
æ¶å°è¯·æ±ä¹å马ä¸ç»åºåé¦ååå»åäºæ
å°±æ¯éé»å¡
ï¼4ï¼Webflux ç¹ç¹ï¼
第ä¸ä¸ª éé»å¡å¼ï¼å¨æéçèµæºä¸ï¼æé«ç³»ç»ååéå伸缩æ§ï¼å¤çæ´å¤ç请æ±ï¼ä»¥ Reactor 为åºäºååºå¼ç¼ç¨
第äºä¸ª å½æ°å¼ç¼ç¨ï¼Spring5 æ¡æ¶åºäº java8ï¼Webflux ä½¿ç¨ Java8 å½æ°å¼ç¼ç¨æ¹å¼å®ç°è·¯ç±è¯·æ±
ï¼5ï¼æ¯è¾ SpringMVC
ç¬¬ä¸ ä¸¤ä¸ªæ¡æ¶é½å¯ä»¥ä½¿ç¨æ³¨è§£æ¹å¼ï¼é½è¿è¡å¨ Tomcat ç容å¨ä¸
ç¬¬äº SpringMVC éç¨å½ä»¤å¼ç¼ç¨ï¼Webflux éç¨å¼æ¥ååºå¼ç¼ç¨
2ãååºå¼ç¼ç¨
ï¼1ï¼ä»ä¹æ¯ååºå¼ç¼ç¨
ç®ç§°RPï¼Reactive Programmingï¼
ååºå¼ç¼ç¨æ¯ä¸ç§é¢åæ°æ®æµåååä¼ æçç¼ç¨èå¼ãè¿æå³çå¯ä»¥å¨ç¼ç¨è¯è¨ä¸å¾æ¹ä¾¿å°è¡¨è¾¾éææå¨æçæ°æ®æµï¼èç¸å ³ç计ç®æ¨¡åä¼èªå¨å°ååçå¼éè¿æ°æ®æµè¿è¡ä¼ æã
ä¾å¦ï¼å¯¹äº a=b+c è¿ä¸ªè¡¨è¾¾å¼çå¤çï¼å¨å½ä»¤å¼ç¼ç¨ä¸ï¼ä¼å è®¡ç® b+c çç»æï¼åææ¤ç»æèµå¼ç» åéaï¼å æ¤ bï¼c 两å¼çååä¸ä¼å¯¹ åéa 产çå½±åãä½å¨ååºå¼ç¼ç¨ä¸ï¼åéa çå¼ä¼éæ¶è·é bï¼c çååèååã
çµåè¡¨æ ¼ç¨åºå°±æ¯ååºå¼ç¼ç¨çä¸ä¸ªä¾åãåå æ ¼å¯ä»¥å å«åé¢å¼æ类似"=B1+C1"çå ¬å¼ï¼èå å«å ¬å¼çåå æ ¼çå¼ä¼ä¾æ®å ¶ä»åå æ ¼çå¼çååèååã
ååºå¼ç¼ç¨æåæ¯ä¸ºäºç®å交äºå¼ç¨æ·çé¢çå建åå®æ¶ç³»ç»å¨ç»çç»å¶èæåºæ¥çä¸ç§æ¹æ³ï¼ä½å®æ¬è´¨ä¸æ¯ä¸ç§éç¨çç¼ç¨èå¼ã
ä¾å¦ï¼å¨MVC软件æ¶æä¸ï¼ååºå¼ç¼ç¨å 许å°ç¸å ³æ¨¡åçååèªå¨åæ å°è§å¾ä¸ï¼åä¹äº¦ç¶ã
ï¼8ï¼Java8 åå ¶ä¹åçæ¬
- éè¿çè§å¯è
模å¼ä¸¤ä¸ªç±»
åObserver
Observable
代ç æ¼ç¤ºï¼
import java.util.Observable;
public class ObserverDemo extends Observable {
public static void main(String[] args) {
ObserverDemo observer = new ObserverDemo();
// æ·»å è§å¯è
observer.addObserver((o,rag)->{
System.out.println("åéåå");
});
observer.addObserver((o,rag)->{
System.out.println("æå¨è¢«è§å¯è
éç¥ï¼åå¤æ¹å");
});
observer.setChanged(); // çæ§æ°æ®åå
observer.notifyObservers(); // éç¥
}
}
è¿è¡ï¼
æå¨è¢«è§å¯è
éç¥ï¼åå¤æ¹å
åéåå
3ãååºå¼ç¼ç¨ï¼ Reactor å®ç°ï¼
ï¼1ï¼ååºå¼ç¼ç¨æä½ä¸ï¼Reactor æ¯æ»¡è¶³ Reactive è§è
ï¼2ï¼Reactor æä¸¤ä¸ªæ ¸å¿ç±»ï¼Mono å Fluxï¼è¿ä¸¤ä¸ªç±»å®ç°æ¥å£ Publisherï¼æä¾ä¸°å¯æä½ç¬¦ãFlux 对象å®ç°åå¸è ï¼è¿å N 个å ç´ ï¼Mono ä¹å®ç°åå¸è ï¼è¿å 0 æè 1 个å ç´
ï¼3ï¼Mono å Flux é½æ¯æ°æ®æµçåå¸è ï¼ä½¿ç¨ Mono å Flux é½å¯ä»¥ååºä¸ç§æ°æ®ä¿¡å·ï¼å ç´ å¼ãé误信å·ãå®æä¿¡å·ï¼é误信å·åå®æä¿¡å·é½ä»£è¡¨ç»æ¢ä¿¡å·ï¼ç»æ¢ä¿¡å·ç¨äºåè¯è®¢é è æ°æ®æµç»æäºï¼é误信å·ç»æ¢æ°æ®æµåæ¶æé误信æ¯ä¼ éç»è®¢é è
ï¼4ï¼ä»£ç æ¼ç¤º Mono å Flux
第ä¸æ¥ å¼å ¥ä¾èµï¼
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.2.5.RELEASE</version>
</dependency>
第äºæ¥ ç¼å代ç
public static void main(String[] args) {
// åå¸å
ç´ justæ¹æ³ç´æ¥å£°æ
Flux.just(1,2,3,4);
Mono.just(1);
// æ°ç»
Integer[] array = {1,2,3,4};
Flux.fromArray(array);
// éå
List<Integer> list = Arrays.asList(array);
Flux.fromIterable(list);
// æµ
Stream<Integer> stream = list.stream();
Flux.fromStream(stream);
}
ï¼5ï¼ä¸ç§ä¿¡å·ç¹ç¹
é误信å·åå®æä¿¡å·é½æ¯ç»æ¢ä¿¡å·ï¼ä¸è½å
±å
å¦æ没æåçä»»ä½å
ç´ å¼ï¼èæ¯ç´æ¥åéé误æè
å®æä¿¡å·ï¼è¡¨ç¤ºæ¯ç©ºæ°æ®æµ
å¦æ没æé误信å·ï¼æ²¡æå®æä¿¡å·ï¼è¡¨ç¤ºæ¯æ éæ°æ®æµ
é误信å·
Flux.error(Throwable error);
ï¼6ï¼è°ç¨ just æè å ¶ä»æ¹æ³åªæ¯å£°ææ°æ®æµï¼æ°æ®æµæ²¡æååºï¼åªæè¿è¡è®¢é ä¹åæä¼è§¦åæ°æ®æµï¼ä¸è®¢é ä»ä¹é½ä¸ä¼åçç
åå¸-订é
public static void main(String[] args) {
// åå¸å
ç´ justæ¹æ³ç´æ¥å£°æ
Flux.just(1,2,3,4).subscribe(System.out::println);
Mono.just(1).subscribe(System.out::println);
}
æ§å¶å°è¾åºï¼
ï¼7ï¼æä½ç¬¦
对æ°æ®æµè¿è¡ä¸ééæä½ï¼æ为æä½ç¬¦ï¼æ¯å¦å·¥åæµæ°´çº¿
第ä¸
map
å ç´ æ å°ä¸ºæ°å ç´
第äº
flatMap
å ç´ æ å°ä¸ºæµ
- ææ¯ä¸ªå ç´ è½¬æ¢æµï¼æ转æ¢ä¹åå¤ä¸ªæµå并大çæµ
4ãWebflux æ§è¡æµç¨åæ ¸å¿ API
SpringWebFlux æ¯åºäº Reactor å®ç°ï¼é»è®¤å®¹å¨æ¯ Netty æ¯é«æ§è½ï¼NIO æ¡æ¶ï¼å¼æ¥éé»å¡æ¡æ¶
ï¼1ï¼Netty
- BIO é»å¡
spring5架構一、Spring 架構概述二、IOC容器三、Aop四、JdbTemplate五、事務管理六、Spring5 新特性 - NIO éé»å¡
spring5架構一、Spring 架構概述二、IOC容器三、Aop四、JdbTemplate五、事務管理六、Spring5 新特性
ï¼2ï¼SpringWebflux æ§è¡è¿ç¨å SringMVC ç¸ä¼¼
- SpringWebflux æ ¸å¿æ§å¶å¨
ï¼å®ç°æ¥å£DispatcherHandler
WebHandler
- æ¥å£
æä¸ä¸ªæ¹æ³WebHandler
handle
ä¿®æ¹ä¾èµ
artifactId
ï¼
spring-boot-starter
为âspring-boot-starter-webfluxâ
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
WebHandler
æºç :
package org.springframework.web.server;
import reactor.core.publisher.Mono;
public interface WebHandler {
Mono<Void> handle(ServerWebExchange var1);
}
æºç å®ç°ï¼
package org.springframework.web.reactive;
...
public class DispatcherHandler implements WebHandler, ApplicationContextAware {
....
public Mono<Void> handle(ServerWebExchange exchange) {// æ¾å
¥http请æ±ååºä¿¡æ¯
return this.handlerMappings == null ? this.createNotFoundError() : Flux.fromIterable(this.handlerMappings).concatMap((mapping) -> {
return mapping.getHandler(exchange);//æ ¹æ®è¯·æ±å°åè·å对åºç mapping
}).next().switchIfEmpty(this.createNotFoundError()).flatMap((handler) -> {
return this.invokeHandler(exchange, handler);// è°ç¨å
·ä½çä¸å¡æ¹æ³
}).flatMap((result) -> {
return this.handleResult(exchange, result);// å¤çç»æè¿å
});
}
...
}
ï¼3ï¼SpringWebflux éé¢æ ¸å¿æ§å¶å¨
DispatcherHnadler
ï¼è´è´£è¯·æ±çå¤ç
-
ï¼è¯·æ±æ¥è¯¢å°å¤ççæ¹æ³HandlerMapping
-
ï¼çæ£è´è´£å¤çä¸å¡è¯·æ±å¤çHandlerAdapter
-
ï¼ååºç»æå¤çHandlerResultHandler
ï¼4ï¼SpringWebflux å®ç°å½æ°å¼ç¼ç¨ï¼ä¸¤ä¸ªæ¥å£ï¼
RouterFunction
(è·¯ç±å¤ç) å
HandlerFunction
(å¤çå½æ°)
5ãSpringWebflux ï¼åºäºæ³¨è§£ç¼ç¨æ¨¡åï¼
SpringWebflux å®ç°æ¹å¼æ两ç§ï¼æ³¨è§£ç¼ç¨æ¨¡ååå½æ°å¼ç¼ç¨æ¨¡å
使ç¨æ³¨è§£ç¼ç¨æ¨¡åæ¹å¼ï¼åä¹å SpringMVC 使ç¨ç¸ä¼¼ï¼åªéè¦æç¸å ³ä¾èµé ç½®å°é¡¹ç®ä¸ï¼
SpringBoot èªå¨é ç½®ç¸å ³è¿è¡å®¹å¨ï¼é»è®¤æ åµä¸ä½¿ç¨ Netty æå¡å¨
第ä¸æ¥ å建 SpringBoot å·¥ç¨ï¼webfluxdemo1ï¼ï¼å¼å ¥ Webflux ä¾èµ
ä¿®æ¹pomæ件ï¼
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/><!-- lookup parent from repository -->
</parent>
<groupId>com.zzp</groupId>
<artifactId>webfluxdemo1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>webfluxdemo1</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- å¼å
¥webfluxä¾èµ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
第äºæ¥ é ç½®å¯å¨ç端å£å·
server.port=8081
# åºç¨å称
spring.application.name=webfluxdemo1
第ä¸æ¥ å建å åç¸å ³ç±»
- å®ä½ç±»
package com.zzp.spring.entity;
//å®ä½ç±»
public class User {
private String name;
private String gender;
private Integer age;
public User(String name, String gender, Integer age) {
this.name = name;
this.gender = gender;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
- å建æ¥å£å®ä¹æä½æ¹æ³
package com.zzp.spring.service;
import com.zzp.spring.entity.User;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
//ç¨æ·æä½æ¥å£
public interface UserService {
//æ ¹æ®idæ¥è¯¢ç¨æ·
Mono<User> getUserById(int id);
//æ¥è¯¢ææç¨æ·
Flux<User> getAllUser();
//æ·»å ç¨æ·
Mono<Void> saveUserInfo(Mono<User> user);
}
- æ¥å£å®ç°ç±»
package com.zzp.spring.service.impl;
import com.zzp.spring.entity.User;
import com.zzp.spring.service.UserService;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.HashMap;
import java.util.Map;
@Repository
public class UserServiceImpl implements UserService {
//å建mapéååå¨æ°æ®
private final Map<Integer,User> userMap = new HashMap<>();
public UserServiceImpl(){
this.userMap.put(1,new User("å°æ","ç·",20));
this.userMap.put(2,new User("å°ç","ç·",30));
this.userMap.put(3,new User("å°è³","女",25));
}
//æ ¹æ®idæ¥è¯¢
@Override
public Mono<User> getUserById(int id) {
return Mono.justOrEmpty(this.userMap.get(id));
}
//æ¥è¯¢ææç¨æ·
@Override
public Flux<User> getAllUser() {
return Flux.fromIterable(this.userMap.values());
}
//æ·»å ç¨æ·
@Override
public Mono<Void> saveUserInfo(Mono<User> userMono) {
return userMono.doOnNext(person->{
//åmapéåéé¢æ¾å¼
int size = userMap.size() + 1;
userMap.put(size,person);
}).thenEmpty(Mono.empty());
}
}
- å建 controller
package com.zzp.spring.controller;
import com.zzp.spring.entity.User;
import com.zzp.spring.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
public class UserController {
//注å
¥service
@Autowired
private UserService userService;
//idæ¥è¯¢
@GetMapping("/user/{id}")
public Mono<User> getUserId(@PathVariable int id){
return userService.getUserById(id);
}
//æ¥è¯¢ææ
@GetMapping("/user")
public Flux<User> getUsers(){
return userService.getAllUser();
}
//æ·»å
@GetMapping("/saveuser")
public Mono<Void> saveUser(@RequestBody User user){
Mono<User> userMono = Mono.just(user);
return userService.saveUserInfo(userMono);
}
}
å¯å¨ï¼æµè¯
idæ¥è¯¢ï¼http://localhost:8081/user/1
æ¥ææï¼http://localhost:8081/user
- 说æ
SpringMVC æ¹å¼å®ç°ï¼åæ¥é»å¡çæ¹å¼ï¼åºäº
SpringMVC + Servlet + Tomcat
SpringWebflux æ¹å¼å®ç°ï¼å¼æ¥éé»å¡ï¼åºäº
SpringWebflux + Reactor + Netty
6ãSpringWebflux ï¼åºäºå½æ°å¼ç¼ç¨æ¨¡åï¼
ï¼1ï¼å¨ä½¿ç¨å½æ°å¼ç¼ç¨æ¨¡åæä½çæ¶åï¼éè¦èªå·±åå§åæå¡å¨ï¼
Netty
ï¼
ï¼2ï¼åºäºå½æ°å¼ç¼ç¨æ¨¡åæ¶åï¼æä¸¤ä¸ªæ ¸å¿æ¥å£ï¼
-
ï¼å®ç°è·¯ç±åè½ï¼è¯·æ±è½¬åç»å¯¹åºçRouterFunction
handler
-
HandlerFunction
ï¼å¤ç请æ±çæååºçå½æ°
æ ¸å¿ä»»å¡å®ä¹è¿ä¸¤ä¸ªå½æ°å¼æ¥å£çå®ç°å¹¶ä¸å¯å¨éè¦çæå¡å¨ã
ï¼3ï¼SpringWebflux 请æ±åååºä¸åæ¯
ServletRequest
å
ServletResponse
ï¼èæ¯
ServerRequest
å
ServerResponse
第ä¸æ¥ æ注解ç¼ç¨æ¨¡åå·¥ç¨å¤å¶ä¸ä»½
第äºæ¥ å建
Handler
ï¼å ·ä½å®ç°æ¹æ³ï¼
package com.zzp.spring.handler;
import com.zzp.spring.entity.User;
import com.zzp.spring.service.UserService;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public class UserHandler {
private UserService userService;
public UserHandler(UserService userService){
this.userService = userService;
}
//æ ¹æ®idæ¥è¯¢
public Mono<ServerResponse> getUserById(ServerRequest request){
// è·åidå¼
int userId = Integer.valueOf(request.pathVariable("id"));
//空置å¤ç
Mono<ServerResponse> notFound = ServerResponse.notFound().build();
// è°ç¨serviceæ¹æ³å¾å°æ°æ®
Mono<User> userMono = this.userService.getUserById(userId);
// æuserMonoè¿è¡è½¬æ¢è¿å
// ä½¿ç¨ Reactoræä½ç¬¦ flatMap
return userMono.flatMap(person ->
ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(Mono.just(person), User.class))
.switchIfEmpty(notFound);
}
//æ¥è¯¢ææ
public Mono<ServerResponse> getAllUsers(ServerRequest request){
//è°ç¨serviceå¾å°ç»æ
Flux<User> users = this.userService.getAllUser();
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(users,User.class);
}
//æ·»å
public Mono<ServerResponse> saveUser(ServerRequest request){
//å¾å°user对象
Mono<User> userMono = request.bodyToMono(User.class);
return ServerResponse.ok().build(this.userService.saveUserInfo(userMono));
}
}
第ä¸æ¥ åå§åæå¡å¨ï¼ç¼å
Router
- å建路ç±çæ¹æ³
package com.zzp.spring;
import com.zzp.spring.handler.UserHandler;
import com.zzp.spring.service.UserService;
import com.zzp.spring.service.impl.UserServiceImpl;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
public class Server {
//1ãå建Routerè·¯ç±
public RouterFunction<ServerResponse> routerFunction(){
//å建handler对象
UserService userService = new UserServiceImpl();
UserHandler handler = new UserHandler(userService);
//设置路ç±
return RouterFunctions.route(
GET("/user/{id}").and(accept(APPLICATION_JSON)),handler::getUserById)
.andRoute(GET("/users").and(accept(APPLICATION_JSON)),handler::getAllUsers);
}
- å建æå¡å¨å®æéé
package com.zzp.spring;
import com.zzp.spring.handler.UserHandler;
import com.zzp.spring.service.UserService;
import com.zzp.spring.service.impl.UserServiceImpl;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.netty.http.server.HttpServer;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler;
public class Server {
//1ãå建Routerè·¯ç±
public RouterFunction<ServerResponse> routerFunction(){...}
//2ãå建æå¡å¨å®æéé
public void createReactorServer(){
//è·¯ç±åhandleréé
RouterFunction<ServerResponse> route = routerFunction();
HttpHandler httpHandler = toHttpHandler(route);
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
//å建æå¡å¨
HttpServer httpServer = HttpServer.create();
httpServer.handle(adapter).bindNow();
}
}
- æç»è°ç¨
public static void main(String[] args) throws IOException {
Server server = new Server();
server.createReactorServer();
System.out.println("enter to exit");
System.in.read();
}
æ§è¡æµè¯ï¼
ï¼4) ä½¿ç¨ WebClinet è°ç¨
å æ§è¡å½æ°å¼ç¼ç¨æ¨¡å
Serverç±» mian
æ¹æ³ï¼è·å端å£å·
package com.zzp.spring;
import com.zzp.spring.entity.User;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
public class Clinet {
public static void main(String[] args) {
//è°ç¨æå¡å¨å°å
WebClient webClient = WebClient.create("http://127.0.0.1:52565");
//æ ¹æ®idæ¥è¯¢
String id = "1";
User user = webClient.get().uri("/user/{id}",id)
.accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(User.class).block();
System.out.println(user.getName());
//æ¥è¯¢ææ
Flux<User> userFlux = webClient.get().uri("/users")
.accept(MediaType.APPLICATION_JSON).retrieve().bodyToFlux(User.class);
userFlux.map(per -> per.getName())
.buffer().doOnNext(System.out::println).blockFirst();
}
}
æ§è¡ï¼æ¥éäº
User
ç±»å建æ åæé
public class User {
...
public User() {
}
...
åæ§è¡ï¼æ¥çæ§å¶å°è¾åº