1. 程式人生 > >Spring(2)之 (2.1 Spring AOP 開發)

Spring(2)之 (2.1 Spring AOP 開發)

在Spring AOP程式設計中:

如果加入容器中的目標物件有實現介面,用 JDK代理;
如果目標物件沒有實現介面,用 Cglib代理;

手動實現 AOP程式設計:

AOP面向切面程式設計: AOP業務程式碼與關注點程式碼分離;
關注點: 重複的程式碼方法)叫關注點;
切面: 關注點形成的類叫切面類;
AOP: 關注點程式碼只寫一次;
       開發者只需要關注核心程式碼;
       執行時,執行核心業務程式碼,動態植入關注點程式碼【用代理類】

1. 沒有用代理類時,直接在實現類即目標物件中新增程式碼——》將程式碼提取出來形成方法——》將重複程式碼形成的方法提取出來形成類,再在目標類的業務程式碼前後呼叫生成的類物件中的關注點程式碼(所以要想呼叫關注點程式碼形成的類中的方法,目標類中就要有相對應的物件屬性):目標物件中要用到 MyAop類物件 aop,用註解生成,所以 MyAop.java類新增 @Component註解自動形成物件;再注入進目標物件,所以類中屬性 aop前新增@Resource註解將容器中生成的 MyAop 物件aop注入進來;再在業務程式碼前後呼叫物件 aop中的方法(中的關注點程式碼); 測試類中最終要呼叫目標物件中的方法,要得到目標類的 bean物件 userDao,所以 UserDao.java類上新增@Component(“userDao”)註解在容器中生成 userDao物件。


1.1 IUserDao.java
(介面中有一個 save方法)

public interface IUserDao{
	public void save() throws Exception;
}

1.2 UserDao.java(目標物件提取成單獨類之前:)
(直接在實現類即目標物件中新增程式碼——》將重複程式碼提取出來形成方法——》將重複程式碼形成的方法提取出來形成類)

public class UserDao implements IUserDao{
	public void save() throws Exception{
		//System.out.println("開始事務"); //關注點程式碼(開始事務)
		beginTrans();     //業務程式碼
		System.out.println("----資料已儲存----"); //關注點程式碼(提交事務)
		commitTrans();
		//System.out.println("提交事務"); //提交事務
	}
	
	public void beginTrans(){
		System.out.println("開始事務");
	}
	public void commitTrans(){
		System.out.println("提交事務");
	}
}

1.2 UserDao.java(目標物件提取成單獨類之後:)
(UserDao中要用到 aop物件,用註解生成,所以 MyAop.java類新增 @Component註解自動形成物件;再注入進來,所以類中 aop前新增@Resource註解將容器中生成的 MyAop 物件aop注入進來;再在業務程式碼前後呼叫物件 aop中的方法;)

@Component("userDao")
public class UserDao implements IUserDao{
        @Resource
	private MyAop aop;
	public void save() throws Exception{	
		aop.beginTrans();
		System.out.println("----資料已儲存----");
		aop.commitTrans();
	}
}

1.3 MyAop.java
(目標物件提取後形成的單獨類)

@Component
public class MyAop{
	public void beginTrans(){
		System.out.println("開始事務");
	}
	public void commitTrans(){
		System.out.println("提交事務");
	}
}

1.4 bean.xml
(IOC容器用註解自動生成bean物件之前開啟Spring掃描)

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- base-package掃描包即子包下的類 -->
    <context:component-scan base-package="com.asd.myaop"></context:component-scan>
    
</beans>

Test.java
(要用到 UserDao的 bean物件userDao,所以 UserDao.java類上新增@Component註解;)

public class Test{
	public static void main(String[] args) {
		ApplicationContext applicationContext=new ApplicationContext("bean.xml");
		IUserDao userDao=(IUserDao)applicationContext.getBean("userDao");
		try{
			userDao.save();
		}catch(Exception e){
			e.printStackTrace();
		}				
	}
}

執行結果:
在這裡插入圖片描述

2. 手動實現利用代理工廠實現AOP
(① ProxyFactory.java類中有兩個屬性:private static Object target; private static MyAop aop;:目標物件、myAop物件,所以在對應的兩個類上分別用@Component(“userDao”)註解生成對應的兩個 bean物件; ② 在 bean1.xml中利用靜態方法生成對應bean物件 userProxy,且將兩個屬性注入;③ Test.java中得到 userProxy的 bean物件,呼叫其 save方法;)
2.1 IUserDao.java

public interface IUserDao{
	public void save() throws Exception;
}

2.2 UserDao.java(目標物件)

@Component("userDao")
public class UserDao implements IUserDao{
	public void save() throws Exception{	
		System.out.println("----資料已儲存----");
	}
}

2.3 MyAop.java
(目標物件提取後形成的單獨類)

@Component
public class MyAop{
	public void beginTrans(){
		System.out.println("開始事務");
	}
	public void commitTrans(){
		System.out.println("提交事務");
	}
}

2.4 ProxyFactory.java

public class ProxyFactory{
	//目標物件
	private static Object target;
	private static MyAop aop;
	//代理物件
	public static Object getProxyFactory(Object _target,MyAop _aop){
		target _target;
		aop _aop;
		return Proxy.newProxyInstance(
			target.getClass().getClassLoader(),
			target.getClass.getInterfaces(),
			new InvocationHandler(){
				public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
					aop.beginTrans();
					Object resultValue=method.invoke(target,args);
					aop.commitTrans();
					return resultValue;
				}
			}
		);
	}	
}

2.5 bean1.xml
(ProxyFactory類中 getProxyFactory是靜態方法,ref 引用 IOC容器中已經生成的 userDao物件(UserDao.java類上@Component(“userDao”)註解生成),)

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- base-package掃描包即子包下的類 -->
    <context:component-scan base-package="com.asd.myaop1"></context:component-scan>
    
    //ProxyFactory類中 getProxyFactory是靜態方法
    <bean id="userProxy" class="com.asd.myaop1.ProxyFactory" factory-method="getProxyFactory">
  	<constructor-arg index="0" ref="userDao"></constructor-arg>
  	<constructor-arg index="1" ref="myAop"></constructor-arg>
    </bean>
    
</beans>

Test.java

public class Test{
	public static void main(String[] args) {
		ApplicationContext applicationContext=new ApplicationContext("bean1.xml");
		IUserDao proxy=(IUserDao)applicationContext.getBean("userProxy");
		try{
			proxy.save();
		}catch(Exception e){
			e.printStackTrace();
		}				
	}
}

執行結果:
在這裡插入圖片描述