Spring 的 IOC 和 AOP的簡單實現
一、IOC
1、配置檔案實現IOC
IOC :控制反轉,將建立物件的控制權又之前的new轉移給Spring框架,目的是為了解耦。
- 匯入相應的Jar包。
- 匯入配置檔案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" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa" 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-3.2.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd"> <!-- 菜系類 --> <bean id="cuisine" class="com.bb.hrb.pojo.Cuisine"> <!-- <property name="name" value="魯菜"></property>--> <constructor-arg index="0" value="東北菜"></constructor-arg> </bean> <!-- 菜品類 --> <bean id="food" class="com.bb.hrb.pojo.Food"> <!-- 通過setter方法進行依賴注入,直接引用上面的id為cuisine屬性賦值 --> <!-- <property name="cuisine" ref="cuisine"></property>--> <!-- 通過構造器進行依賴注入 --> <constructor-arg index="0" value="豬肉燉粉條"></constructor-arg> <constructor-arg index="1" value="36.8"></constructor-arg> <constructor-arg index="2" ref="cuisine"></constructor-arg> </bean> </beans>
屬性介紹:
<bean id="" class=""></bean> class屬性是用來指明類的包名加類名,id屬性用來獲取這個bean物件 <bean id="" class=""> <property name="" ref=""></property> </bean> property標籤用來通過setter方法進行依賴注入,name屬性是bean物件中屬性名,ref指向一個 bean的id,還可以有value屬性,用於直接設定基本資料型別 <bean id="" class=""> <constructor-arg index="" value="" ref=""></constructor-arg> </bean> constructor-arg標籤是通過構造器進行依賴注入,index屬性指定第幾個構造器引數0為第一個, value用於直接設定基本資料型別。ref指向一個bean的id
-
現在就可以直接使用了!實現如下:
// 讀取配置檔案,如果配置檔案中bean中已經賦值,則返回一個賦好值得物件,反之則返回空物件
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//food為配置檔案裡的id
Food food = (Food) ac.getBean("food");
System.out.println(food);
2、註解實現IOC
使用註解只需要在Spring配置檔案中新增標籤:自動掃描註解
<context:component-scan base-package="com.bb.hrb"></context:component-scan>
1、bean註解
@Control 用於控制層元件
@Service 用於業務層元件
@Respository 用於DAO層元件
@Component 用於其它元件
以上註解使用後都可以建立bean物件,沒有區別,不同的使用只是便於分層理解
添加註解之後預設將類名(首字母小寫)定義為bean的id名,id也可以自己定義(註解後
新增小括號雙引號,在其中新增自定義的id名)
2、依賴注入註解
@Resource JDK提供的
@AutoWired Spring提供的 預設按照型別匹配,也可指定id
@Qualifier 配合@AutoWired使用,用於指定注入的bean的id
二、AOP
1、配置檔案實現AOP
AOP: "面向切面程式設計"或者叫做"面向方面程式設計"
可以動態的在一個類的方法執行前後自動之前其它類的方法,在不改變這兩個類程式碼的前提下就可以實現,這種程式設計思想就是"面向切面程式設計",當不再需要使用時可以自由分開。
1、首先還是匯入相應的jar包
2、模擬建立 兩個類
UserService類
public class UserService{
public void addUser() {
System.out.println("使用者註冊");
}
public String deleteUser() {
System.out.println("刪除使用者");
String name = null;
try{
name.length();
} catch(Exception ex) {}
return "success";
}
}
UserLogging通知類
import org.aspectj.lang.ProceedingJoinPoint;
public class UserLogging {
public void logger() {
System.out.println("前置通知...");
}
public void afterLogger() {
System.out.println("最終通知...");
}
public void afterLoggerReturning(Object ret) {
System.out.println("後置通知..." + ", 返回值是:" + ret);
}
public void afterLoggerThrowing(Exception ex) {
System.out.println("異常通知...");
//ex.printStackTrace();
}
/*
* 環繞通知需要ProceedingJoinPoint執行proceed()目標方法
* 並且需要return執行proceed()後的返回值
*/
public Object aroundLogger(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("環繞通知前部...");
Object r = pjp.proceed();// 執行目標方法
System.out.println("環繞通知後部...");
return r;
}
}
3、然後在Spring配置檔案中加入
<bean id="userService" class="com.oracle.service.UserServiceImpl"></bean>
<bean id="logg" class="com.oracle.aop.UserLogging"></bean>
<aop:config>
<!-- 定義切入點 -->
<!-- 第一個*代表返回值,第二個*代表類,第三個*代表方法,(..)所有的過載方法,..表示任意的引數列表 -->
<aop:pointcut expression="execution(* com.oracle.service.*.*(..))" id="servicePointcut"/>
<!-- 配置切面 -->
<aop:aspect id="loggeraspect" ref="logg">
<!-- 前置通知 -->
<aop:before method="logger" pointcut-ref="servicePointcut"/>
<!-- 最終通知 -->
<aop:after method="afterLogger" pointcut-ref="servicePointcut"/>
<!-- 後置通知 returning="ret"的值要和異常通知的方法的引數一致 -->
<aop:after-returning method="afterLoggerReturning" pointcut-ref="servicePointcut" returning="ret"/>
<!-- 異常通知 throwing="ex"的值要和異常通知的方法的引數一致 -->
<aop:after-throwing method="afterLoggerThrowing" pointcut-ref="servicePointcut" throwing="ex"/>
<!-- 環繞通知 -->
<aop:around method="aroundLogger" pointcut-ref="servicePointcut"/>
</aop:aspect>
</aop:config>
4、大功告成,寫一個測試類測試一下吧!
public class TestUserService {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService service = (UserService) ac.getBean("userService");
service.addUser();
String r = service.deleteUser();
System.out.println(r);
}
}
2、註解實現AOP
使用註解只需要在Spring配置檔案中寫兩行
<!-- 註解IOC -->
<context:component-scan base-package="com.oracle"></context:component-scan>
<!-- 註解AOP -->
<aop:aspectj-autoproxy />
舉個栗子:
我們把上面用配置檔案實現的改一下
UserService類:
import org.springframework.stereotype.Service;
@Service("userService")
public class UserService {
public void addUser() {
System.out.println("使用者註冊");
}
public String deleteUser() {
System.out.println("刪除使用者");
String name = null;
try{
name.length();
} catch(Exception ex) {}
return "success";
}
}
UserLogging通知類:這裡只拿前置通知為例
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
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 UserLogging {
// 定義切入點,這個方法就相當於切入點id
@Pointcut("execution(* com.oracle.service.*.*(..))")
public void servicePointcut(){}
@Before("servicePointcut()")
public void logger() {
System.out.println("前置通知...");
}
public void afterLogger() {
System.out.println("最終通知...");
}
public void afterLoggerReturning(Object ret) {
System.out.println("後置通知..." + ", 返回值是:" + ret);
}
public void afterLoggerThrowing(Exception ex) {
System.out.println("異常通知...");
//ex.printStackTrace();
}
/*
* 環繞通知需要ProceedingJoinPoint執行proceed()目標方法
* 並且需要return執行proceed()後的返回值
*/
public Object aroundLogger(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("環繞通知前部...");
Object r = pjp.proceed();// 執行目標方法
System.out.println("環繞通知後部...");
return r;
}
}
好了可以測試一下了,測試類用上面的就可以。