1. 程式人生 > >Spring 的 IOC 和 AOP的簡單實現

Spring 的 IOC 和 AOP的簡單實現

一、IOC

1、配置檔案實現IOC

IOC :控制反轉,將建立物件的控制權又之前的new轉移給Spring框架,目的是為了解耦。

  1. 匯入相應的Jar包。
  2. 匯入配置檔案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

     

  3. 現在就可以直接使用了!實現如下:

// 讀取配置檔案,如果配置檔案中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;
	}
}

好了可以測試一下了,測試類用上面的就可以。