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();
}
}
}
執行結果: