Spring第二天:Spring的IOC的註解方式、Spring的AOP開發(XML)
Spring第二天繼續,今天要學習的是Spring的IOC的註解方式和Spring的AOP開發(XML)
目錄
2.4Spring的Aop的開發(AspectJ的XML的方式)
2.5Spring的Aop的入門(AspectJ的XML的方式)
2.6.5最終通知:無論是否有異常,都執行(相當於try-catch中的finally)
1.Spring的IOC註解方式開發
1.1Spring的IOC註解開發入門
1.1.1建立Web專案引入Jar包
在Spring4的版本中,除了引入基本的開發包以外,還需要引入aop的包。
1.1.2引入Spring的配置檔案
在src下建立applicationContext.xml,使用註解開發需要引入context的約束。
<?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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
1.1.3建立介面和實現類
介面:
package com.albertyy.spring.demo1;
/**
* 使用者管理DAO層介面
* @author yxy
*
*/
public interface UserDAO {
public void save();
}
實現類:
package com.albertyy.spring.demo1;
/**
* 使用者管理DAO層實現類
* @author yxy
*
*/
public class UserDAOImpl implements UserDAO {
@Override
public void save() {
System.out.println("UserDAOImpl執行了...");
}
}
1.1.4開啟Spring的元件掃描
<!-- Spring的IOC的註解入門 -->
<!-- 使用IOC註解開發,配置元件掃描(那些包下的類使用IOC註解) -->
<context:component-scan base-package="com.albertyy.spring.demo1"></context:component-scan>
1.1.5在類上添加註解
package com.albertyy.spring.demo1;
import org.springframework.stereotype.Component;
/**
* 使用者管理DAO層實現類
* @author yxy
*
*/
@Component("userDao") //相當於<bean name="userDAO" class="com.albertyy.spring.demo1.UserDAOImpl" />
public class UserDAOImpl implements UserDAO {
@Override
public void save() {
System.out.println("UserDAOImpl執行了...");
}
}
1.1.6編寫測試類
@Test
/**
* Spring的IOC註解方式
*/
public void demo2(){
// 建立Spring的工廠
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDAO userDAO = (UserDAO) applicationContext.getBean("userDao");
userDAO.save();
}
1.1.7註解方式設定屬性的值
使用註解方式設定值可以沒有set方法。如果屬性有set方法,需要將屬性注入的註解新增到set方法上,如果屬性沒有set方法,將屬性注入的註解新增到屬性上。
/**
* 使用者管理DAO層實現類
* @author yxy
*
*/
@Component("userDao") //相當於<bean name="userDAO" class="com.albertyy.spring.demo1.UserDAOImpl" />
public class UserDAOImpl implements UserDAO {
@Value("李四")
private String name;
// @Value("張三")
// public void setName(String name) {
// this.name = name;
// }
@Override
public void save() {
System.out.println("UserDAOImpl執行了..."+name);
}
1.2Spring的IOC註解的詳解
1.2.1IOC註解@component
- 修飾一個類,將這個類交給spring管理這個註解有三個衍生類:
- @Controller:web層
- @service:service層
- @Repository:dao層
@Repository、@Service 和 @Controller。在目前的 Spring 版本中,這 3 個註釋和 @Component 是等效的,但是從註釋類的命名上,很容易看出這3個註釋分別和持久層、業務層和控制層(Web 層)相對應。
1.2.2屬性注入註解
- 普通屬性
- @Value:設定普通屬性的值
- 物件型別屬性
- @Autowired:設定物件型別的屬性的值,但是是按照型別完成屬性注入的。
- 因為我們習慣是按名字完成注入:所以就必須讓!@Autowired和@Qualifier(value=“需要註解的物件的註解名字”)一起使用,完成按照名稱屬性注入。
- 可以用@Resource來替代上面的倆,來完成物件的註解。
@Service("userService")
public class UserServiceImpl implements UserService {
//注入Dao
// @Autowired
// @Qualifier("userDao")
@Resource(name="userDao")
private UserDao userDao;
@Override
public void save() {
userDao.save();
System.out.println("UserService執行了、、、、。。。");
}
}
1.2.3Bean的其他註解
- 生命週期相關的註解(瞭解)
- @PostConstruct:相當於init-method,初始化方法
- @PreDestroy :相當於destroy-method,銷燬方法
- Bean作用範圍的註解
- scope:Bean的作用範圍
- singleton :預設的,Spring會採用單例模式建立這個物件。
- prototype :多例模式。(Struts2和Spring整合一定會用到)
- request :應用在web專案中,Spring建立這個類以後,將這個類存入到request範圍中。
- session :應用在web專案中,Spring建立這個類以後,將這個類存入到session範圍中。
- globalsession :應用在web專案中,必須在porlet環境下使用。但是如果沒有這種環境,相對於session。
1.2.4IOC的XML和註解開發的比較
適用場景:
- xml: 可以適用任何場景 。
- 好處:結構清晰,後期方便維護
- 註解:有些地方用不了,比如:這個類,不是自己提供的 。
- 好處:開發方便
1.2.5 XML和註解混合使用
- XML管理Bean,註解完成屬性注入。
<!-- 在沒有掃描的情況下,使用屬性注入的註解:@Resource,@Value,@Autowired,@Qualifier -->
<context:annotation-config></context:annotation-config>
2.Spring的AOP的XML開發
2.1什麼是Aop
在軟體業,AOP為Aspect Oriented Programming的縮寫,意為:面向切面程式設計,通過預編譯方式和執行期動態代理實現程式功能的統一維護的一種技術。AOP是OOP的延續,是軟體開發中的一個熱點,也是Spring框架中的一個重要內容,是函數語言程式設計的一種衍生範型。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。原有專案功能上,通過aop去新增新的功能,這些功能是建立在原有的功能基礎上的,而且不會修改原來程式碼以及邏輯。
打個不恰當的比方,這就好像我們吃漢堡,想要加個牛排,直接把牛排加在裡面就行了,而不會影響原來漢堡裡面的東西,利用Aop思想程式設計也是同樣的道理,我們想要在程式中新加一個功能,就像在漢堡中加上一個牛排,不會影響原來的程式。
2.2Spring底層的Aop實現原理
- 動態代理
- JDK動態代理:只能對實現了介面的類產生代理
- Cglib動態代理:對沒有實現介面的類產生代理物件,生成子類物件。
反射 用的shiClass
動態代理用的是Proxy
2.3Spring的Aop應用場景
一般來說:列印日誌,還有簡訊通知啊,許可權驗證等,都可以使用aop來實現。
2.4Spring的Aop的開發(AspectJ的XML的方式)
2.4.1Spring的AOP簡介
AOP思想最早是由AOP聯盟組織提出的,Spring是使用這種思想最好的框架。AspectJ是AOP的一個很悠久的實現框架,它能夠和 Java 配合起來使用。Spring有自己的Aop實現,但比較繁瑣,所以引入AspectJ作為自己的店Aop開發方式。
2.4.2 AOP開發中的術語
- 連線點Joinpoint:可以攔截到的點 。
- 切入點Poincut:真正被攔截到的點 。
- 通知Advice:通知,方法層面的增強。
- 引介Introduction:類層面的增強。
- 目標Target:被增強的物件。
- 織入Weaviong:將通知應用(Advice)到目標(Target)的過程 將許可權校驗的方法的程式碼應用到UserDao的save方法的過程就是織入。
- 代理Proxy:被增強後產生的代理物件。
- 切面Aspect:多個通知和多個切入點的組合,比如攔截器。
2.5Spring的Aop的入門(AspectJ的XML的方式)
2.5.1建立web專案,引入jar包
- 引入基本開發包
- 引入aop開發的相關的jar包
2.5.2引入Spring的配置檔案
引入aop的約束
<?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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>
2.5.3編寫目標類並完成配置
目標類:
package com.albertyy.demo1;
public class ProductDaoImpl implements ProductDao {
@Override
public void save() {
System.out.println("儲存");
}
@Override
public void update() {
System.out.println("修改");
}
@Override
public void delete() {
System.out.println("刪除");
}
@Override
public void find() {
System.out.println("查詢");
}
}
配置:
<!-- 配置目標物件,即被增強的物件 -->
<bean id="productDao" class="com.albertyy.demo1.ProductDaoImpl"></bean>
2.5.4編寫測試類
- Spring整合Junit單元測試
引入Spring-test的jar包
程式碼編寫:
package com.albertyy.demo1;
/*
* aop的入門
*/
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo1 {
@Resource(name="productDao")
private ProductDao pd;
@Test
public void demo1() {
pd.delete();
pd.save();
pd.find();
pd.update();
}
}
2.5.5編寫一個切面類
- 編寫切面
package com.albertyy.demo1;
/**
*
* 專案名稱:Spring_AOP
* 類名稱:MyAspectXML
* 類描述:切面類
* 建立人:yangyangyang
* 建立時間:2018年12月4日 下午6:11:42
* 修改人:yangyangyang
* 修改時間:2018年12月4日 下午6:11:42
* 修改備註:
* @version
*
*/
public class MyAspectXML {
public void checkPri(){
System.out.println("-------許可權校驗------");
}
}
- 配置切面:將切面類交給Spring管理
<!-- 將切面類交給Spring管理 -->
<bean id="myAspect" class="com.albertyy.demo1.MyAspectXML"></bean>
2.5.6通過AOP配置實對目標類產生代理
<!-- 通過AOP配置對目標類產生代理 -->
<aop:config>
<!-- 表示式配置哪些類的那些方法需要進行增強 -->
<aop:pointcut expression="execution(* com.albertyy.demo1.ProductDaoImpl.save(..))" id="pointcut1"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspect">
<aop:before method="checkPri" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
2.6Spring的通知型別
2.6.1前置通知:在目標方法執行之前進行操作
- 前置通知:可以獲得切入點的資訊。
- 在切面類的前置通知的方法內傳入一個傳入引數(JoinPoint jp)然後列印就可以獲得切入點的資訊。
public class MyAspectXML {
/*
* 前置通知
*/
public void checkPri(JoinPoint jp){
System.out.println("-------許可權校驗------"+jp);
}
}
<!-- 配置切面 -->
<aop:aspect ref="myAspect">
<aop:before method="checkPri" pointcut-ref="pointcut1"/>
</aop:aspect>
2.6.2後置通知:在目標方法執行之後進行操作
- 後置通知:可以獲得方法的返回值。
- 在切面類的後置通知的方法內傳入一個Object型別的以配置檔案中返回值returning為名字的引數 列印即可獲得切入點的返回值。
/*
* 後置通知
*/
public void writeLog(Object result){
System.out.println("-------日誌記錄------"+result);
}
<!-- 配置切面 -->
<aop:aspect ref="myAspect">
<!-- 前置通知 -->
<aop:before method="checkPri" pointcut-ref="pointcut1"/>
<!-- 後置通知 -->
<aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="result"/>
</aop:aspect>>
2.6.3環繞通知:在目標方法執行之前和之後進行操作
- 環繞通知:阻止目標方法的執行。
/*
* 環繞通知:效能監控
*/
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("-----環繞前通知-------");
Object b= joinPoint.proceed();
System.out.println("-----環繞後通知-------");
return b;
}
<!-- 環繞通知 -->
<aop:around method="around" pointcut-ref="pointcut3" />
2.6.4異常丟擲通知:在程式丟擲異常的時候進行操作
/*
* 異常丟擲通知
*/
public void afterThrowing(Throwable ex){
System.out.println("-----異常丟擲通知-------"+ex.getMessage());
}
<!-- 異常丟擲通知 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>
2.6.5最終通知:無論是否有異常,都執行(相當於try-catch中的finally)
//最終通知:相當於finally
public void after(){
System.out.println("-----最終通知");
}
<!-- 最終通知 -->
<aop:after method="after" pointcut-ref="pointcut4" />
2.6.6引介通知(略)
2.7Spring切入點的表示式語法
- 基於execution的函式完成的
- 語法:
- [訪問修飾符] 方法返回值 包名.類名.方法名(引數) 。
- public void com.spring.CustomerDao.save(..) 返回值為void型別在包com.spring下CustomerDao類中的切入點save()方法,傳入的切入點的引數為任意型別。
- *.*.*Dao.save(..) 任意返回值,任意包下的名字下的Dao類的save方法,傳入的切入點的引數為任意型別 。
- com.spring.CustomerDao+.save(..) 返回值為任意型別在包com.spring下CustomerDao類及其子類的切入點save(),傳入的切入點的引數為任意型別。
- com.spring.*.*(..)返回值為任意型別在包com.spring下任意類中的任意切入點 切入點傳入的引數為任意型別。
原始碼連結:連結: https://pan.baidu.com/s/1lH8HPS1aalBSYqhMmDZjnQ 提取碼: ihip 複製這段內容後開啟百度網盤手機App,操作更方便哦