初識Spring專案
阿新 • • 發佈:2021-01-20
快速起步
1. 下載依賴包
- spring-beans-5.2.2.RELEASE.jar:包含管理Bean和配置檔案的基本功能
- spring-core-5.2.2.RELEASE.jar:spring核心包
- spring-context-5.2.2.RELEASE.jar:核心擴充套件包,包含大量工具類
- spring-expression-5.2.2.RELEASE.jar:表示式解析語言,支援動態的解析表示式給物件賦值等功能
- commons-logging-1.2.jar:日誌支援包
- log4j-1.2.17.jar:日誌支援包
2. 建立Spring專案
- 建立Web專案
- 將下載好的JAR檔案複製到
WebRoot/WEB-INF/lib
- 建立
resources
資源目錄,並將 log4j.properties 配置檔案拷貝其中 - 建立
test
測試目錄
3. 建立JavaBean
建立 beans.HelloSpring
類
package beans; public class HelloSpring { private String who = null; public String getWho() {return who;} public void setWho(String who) {this.who = who;} public void print(){ System.out.println("Hello, " + this.getWho() +" ! "); } }
4. 建立核心配置檔案
在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-3.2.xsd"> <!-- 通過bean元素宣告需要Spring建立的例項。該例項的型別通過class屬性指定,並通過id屬性為該例項指定一個名稱,以便在程式中使用 --> <bean id="helloSpring" class="beans.HelloSpring"> <!-- property元素用來為例項的屬性賦值,此處實際是呼叫setWho()方法實現賦值操作 --> <property name="who"> <!-- 此處將字串"Spring"賦值給who屬性 --> <value>Spring</value> </property> </bean> </beans>
5. 編寫測試類
在 test
目錄中,建立單元測試類test.SpringTest
package test;
import beans.HelloSpring;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
@Test
public void test() {
// 例項化Spring的上下文
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 獲取bean的例項
HelloSpring helloSpring = (HelloSpring) context.getBean("helloSpring");
// 執行print()方法
helloSpring.print();
}
}
Ioc依賴注入
配置檔案實現
注入字面量
value標籤
<bean id="helloSpring" class="beans.HelloSpring">
<property name="who">
<value>Spring</value>
</property>
</bean>
value屬性
<bean id="helloSpring" class="beans.HelloSpring">
<property name="who" value="value" />
</bean>
P名稱空間
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="helloSpring" class="beans.HelloSpring" p:who="Spring"/>
</beans>
注入物件
內部bean
<bean id="a" class="beans.A">
<property name="b">
<bean class="beans.B">
<property name="str" value="val"></property>
</bean>
</property>
</bean>
ref屬性
<bean id="b" class="beans.B">
<property name="str" value="val"></property>
</bean>
<bean id="a" class="beans.A">
<property name="b" ref="b"></property>
</bean>
ref標籤
<bean id="b" class="beans.B">
<property name="str" value="val"></property>
</bean>
<bean id="a" class="beans.A">
<property name="b">
<ref bean="b"/>
</property>
</bean>
P名稱空間
<beans xmlns:p="http://www.springframework.org/schema/p" ...>
<bean id="b" class="beans.B" p:str="val"/>
<bean id="a" class="beans.A" p:b-ref="b"/>
</beans>
構造注入
構造方法
public A(String strAttr,int intAttr,B b){
// ...
}
引數索引
<bean id="b" class="beans.B" p:str="val"/>
<bean id="printer" class="beans.Printer">
<constructor-arg index="0" value="strValue"/>
<constructor-arg index="1" value="10"/>
<constructor-arg index="2" ref="b"/>
</bean>
引數名稱
<bean id="b" class="beans.B" p:str="val"/>
<bean id="printer" class="beans.Printer">
<constructor-arg name="strAttr" value="strValue"/>
<constructor-arg name="intAttr" value="10"/>
<constructor-arg name="b" ref="b"/>
</bean>
注入null值
<bean id="id" class="package.class">
<property name="attr"><null></null></property>
</bean>
注入空字串
<bean id="id" class="package.class">
<property name="attr"><value></value></property>
</bean>
注入包含特殊字元的值
CDATA
<bean id="id" class="package.class">
<property name="attr"><value><![CDATA[P&G]]></value></property>
</bean>
實體符號
<bean id="printer" class="beans.Printer">
<property name="ink"><value>P&G</value></property>
</bean>
注入List集合
<bean id="id" class="package.class">
<property name="lists">
<list>
<value>黑色</value>
<value>彩色</value>
</list>
</property>
</bean>
注入Set集合
<bean id="id" class="package.class">
<property name="sets">
<set>
<value>黑色</value>
<value>彩色</value>
</set>
</property>
</bean>
注入Map集合
<bean id="id" class="package.class">
<property name="maps">
<map>
<entry>
<key><value>k1</value></key>
<value>v1</value>
</entry>
<entry>
<key><value>k2</value></key>
<value>v2</value>
</entry>
</map>
</property>
</bean>
注入Properties集合
<bean id="id" class="package.class">
<property name="prop">
<props>
<prop key="k1">v1</prop>
<prop key="k2">v2</prop>
</props>
</property>
</bean>
註解實現Ioc
全域性配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.0.xsd">
<!-- 掃描包中註解標註的類 -->
<context:component-scan base-package="beans"/>
</beans>
定義Bean
定義普通Bean
@Component
public class BeanName { /* ... */ }
// 等效於
@Component("beanName")
public class BeanName { /* ... */ }
定義DAO Bean
@Repository
public class BeanDao { /* ... */ }
// 等效於
@Repository("beanDao")
public class BeanDao { /* ... */ }
定義業務Bean
@Service
public class BeanService { /* ... */ }
// 等效於
@Service("beanService")
public class BeanService { /* ... */ }
定義控制器Bean
@Controller
public class BeanController { /* ... */ }
// 等效於
@Controller("beanController")
public class BeanController { /* ... */ }
裝配Bean
以型別裝配
@Autowired
private BeanClass bean;
如果有多個型別相同的Bean,則需要指定Bean名稱
@Autowired
@Qualifier("beanName")
private BeanClass bean;
// 或
private BeanClass bean;
@Autowired
@Qualifier("beanName")
public void setBean(BeanClass bean) { /* ... */ }
// 或
private BeanClass bean;
@Autowired
public void setBean(@Qualifier("beanName")BeanClass bean) { /* ... */ }
構造方法裝配
@Autowired
public Printer(BeanClass bean){/* ... */}
// 或
@Autowired
public Printer(@Qualifier("beanName")BeanClass bean){/* ... */}
阻止Bean元件不存在時報異常
@Autowired(required = false)
private BeanClass bean;
將相同型別的Bean裝配到集合
@Autowired
private List<BeanClass> beans;
優先以名稱裝配,如果沒有找到指定的Bean,則以型別裝配
// 先找名稱為 bean 的 Bean,如果沒有找,則找名稱為 beanClass 的 Bean,如果還沒有找到,則尋找型別為 BeanClass 的 Bean
@Resource
private BeanClass bean;
// 找名稱為 beanName 的 Bean
@Resource(name="beanName")
private BeanClass bean;
// 找名稱為 bean 的 Bean
private BeanClass bean;
@Resource
public void setBean(BeanClass bean) { /* ... */ }
AOP實現
配置檔案實現
1. 下載依賴包
2. 建立被增強類
package aopdemo;
import org.springframework.stereotype.Component;
@Component("a")
public class A {
public void fun1() { /* ... */ }
public void fun2() { throw new RuntimeException("fun2 丟擲異常"); }
public void fun3() { /* ... */ }
public void fun4() { throw new RuntimeException("fun4 丟擲異常"); }
}
3. 建立切面
package aopdemo;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;
@Component
public class AspectImpl {
/**
* 前置增強
* @param joinPoint 切入點物件
*/
public void before(JoinPoint joinPoint) {
System.err.println("正在執行前置增強。。。");
}
/**
* 後置增強
* @param joinPoint 切入點物件
* @param result 被增強方法的返回值
*/
public void afterReturning(JoinPoint joinPoint, Object result) {
System.err.println("正在執行後置增強,返回值為:" + result);
}
/**
* 異常增強
* @param joinPoint 切入點物件
* @param e 被增強方法丟擲的異常物件
*/
public void afterThrowing(JoinPoint joinPoint, RuntimeException e) {
System.err.println("正在執行異常增強,異常為:" + e);
}
/**
* 最終增強
* @param joinPoint 切入點物件
*/
public void after(JoinPoint joinPoint) {
System.err.println("正在執行最終增強。。。");
}
/**
* 環繞增強
* @param joinPoint 切入點物件
* @return 被增強方法的返回值
*/
public Object around(ProceedingJoinPoint joinPoint) {
Object result = null;
try {
System.err.println("開始執行環繞增強。。。");
result = joinPoint.proceed();
System.err.println("結束執行環繞增強。。。");
} catch (Throwable e) {
System.err.println("環繞增強的異常處理:" + e);
} finally {
return result;
}
}
}
4. 全域性配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:component-scan base-package="aopdemo" />
<aop:config>
<!-- 切入點 -->
<aop:pointcut expression="execution(public void fun1())" id="fun1"/>
<aop:pointcut expression="execution(public void fun2())" id="fun2"/>
<aop:pointcut expression="execution(public void fun3())" id="fun3"/>
<aop:pointcut expression="execution(public void fun4())" id="fun4"/>
<!-- 切面 -->
<aop:aspect ref="aspectImpl">
<!-- 前置增強 -->
<aop:before method="before" pointcut-ref="fun1" />
<!-- 後置增強 -->
<aop:after-returning method="afterReturning" pointcut-ref="fun1" returning="result"/>
<!-- 異常增強 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="fun2" throwing="e"/>
<!-- 最終增強 -->
<aop:after method="after" pointcut-ref="fun3"/>
<!-- 環繞增強 -->
<aop:around method="around" pointcut-ref="fun4"/>
</aop:aspect>
</aop:config>
</beans>
5. 編寫測試類
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
A a = (A)context.getBean("a");
// 依次執行一下方法進行測試
// a.fun1();
// a.fun2();
// a.fun3();
a.fun4();
}
註解實現AOP
切面實現類
package aopdemo;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class AspectImpl {
// 定義通用切入點
@Pointcut("execution(public void fun1())")
public void pointcut1() {}
// 前置增強
@Before("pointcut1()")
public void before(JoinPoint joinPoint) { /* ... */ }
// 後置增強
@AfterReturning(pointcut = "pointcut1()", returning = "result")
public void afterReturning(JoinPoint joinPoint, Object result) { /* ... */ }
// 異常增強
@AfterThrowing(pointcut = "execution(public void fun2())", throwing = "e")
public void afterThrowing(JoinPoint joinPoint, RuntimeException e) { /* ... */ }
// 最終增強
@After("execution(public void fun3())")
public void after(JoinPoint joinPoint) { /* ... */ }
// 環繞增強
@Around("execution(public void fun4())")
public Object around(ProceedingJoinPoint joinPoint) { /* ... */ }
}
全域性配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:component-scan base-package="aopdemo" />
<!-- 啟用Aspectj,並自動建立代理 -->
<aop:aspectj-autoproxy/>
</beans>
切入點表示式匹配規則
匹配所有型別的返回值
public * addNewUser(entity.User)
匹配所有方法名
public void *(entity.User)
匹配所有引數個數和型別
public void addNewUser(..)
匹配 com.service 包下所有類的所有方法
* com.service.*.*(..)
匹配 com.service 包及其子包下所有類的所有方法
* com.service..*.*(..)
JoinPoint
獲取目標類完全限定名
joinPoint.getTarget()
獲取目標方法名
joinPoint.getSignature().getName()
獲取目標方法入引數組
joinPoint.getArgs()
ProceedingJoinPoint
獲取目標類完全限定名
joinPoint.getTarget()
獲取目標方法名
joinPoint.getSignature().getName()
獲取目標方法入引數組
joinPoint.getArgs()
執行目標方法並獲取返回值
joinPoint.proceed()