1. AOP:即面向切面編程,採用橫向抽取機制,取代了傳統的繼承體系的重複代碼問題,以下圖所示,性能監控、日誌記錄等代碼圍繞業務邏輯代碼,而這部分代碼是一個高度重複的代碼,也就是在每個業務邏輯的代碼中都會有相同的代碼圍繞業務邏輯代碼,而AOP就是將這些重複代碼抽取出java
2. AOP實現原理:就是代理模式,主要有兩種方式,分別是靜態代理和動態代理,web
3. spring採用動態代理的技術實現包括:spring
cglib經過繼承的形式來實現動態功能的代理 那麼就沒法避免一些繼承的缺點,那就是沒法代理final方法和沒法代理final類,示例使用代碼以下express
import java.lang.reflect.Method; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; public class CglibProxy implements MethodInterceptor { //obj生成的代理對象 //method對目標對象方法的引用 //args目標對象方法調用參數 //MethodProxy代理對象中對方法的引用 @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { //在方法以前加強,開啓事務 System.out.println("開啓事務..."); //執行父類方法 Object result = methodProxy.invokeSuper(obj, args); //在方法以後加強,提交事務 System.out.println("提交事務..."); return result; } } import org.springframework.cglib.proxy.Enhancer; public class CglibProxyFactory { /** * * <p>Title: createCglibProxy</p> * <p>Description: </p> * @param clazz 父類的class,經過class操做字節碼建立代理對象 * @return */ public static Object createCglibProxy(Class clazz){ //代理對象,這裏邊有加強的代碼 CglibProxy cglibProxy = new CglibProxy(); //建立加強器,須要設置父類及代理對象 Enhancer enhancer = new Enhancer(); //在加強器設置父類 enhancer.setSuperclass(clazz); //在加強器設置代理對象(包括加強代碼) enhancer.setCallback(cglibProxy); //建立一個代理對象 return enhancer.create(); } }
4. cglib與jdk實現動態代理的區別:jdk是基於接口生成代理對象,而cglib是基於類生成代理對象。spring底層使用jdk和cglib,若是原始對象實現了一個接口,spring使用jdk,不然 使用cglib生成代理。apache
5. 相關術語:編程
1. 搭建環境:經過Maven加入spring-webmvc.jar和aspectjweaver.jar包便可導入全部須要依賴的包spring-mvc
2. AspectJ相關語法:mvc
public void save(){ try{ //前置加強 調用目標對象方法執行 //後置加強 }catch(Exception ex){ //拋出異常加強 }finally{ //最終finally加強 } }
3. 在Spring中的AOP配置:ide
<?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"> <!--配置AOP中的加強類,即將LoggerBean中的方法做用到Controller組件的全部方法上--> <bean id="loggerBean" class="LoggerBean"></bean> <!--配置AOP--> <aop:config> <!--配置切面:切面包括切點和加強 --> <aop:aspect ref="loggerBean"><!--ref屬性就表示指定加強類--> <!--配置切點 --> <aop:pointcut expression="execution(* controller.user.*.*(..))" id="point"/> <!--配置前置加強 ,加強就是 LoggerBean類中的logController方法--> <aop:before method="logController" pointcut-ref="point"/> <!-- 配置後置加強,加強就是 LoggerBean類中的outController方法--> <aop:after-returning method="outController" pointcut-ref="point"/> </aop:aspect> </aop:config> <!--開啓註解掃描,只有被掃描進Spring容器的類才能配置AOP來加強代碼--> <context:component-scan base-package="controller.user"></context:component-scan> <!--若是要經過AOP註解來配置AOP,除了context:component-scan標籤,還有下面這個標籤開啓AOP註解標示的使用--> <aop:aspectj-autoproxy/> </beans>
import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; //一個簡單的日誌記錄加強代碼 @Component//掃描添加到spring容器 @Aspect//將組件指定爲切面組件 public class ExceptionBean { //e就是目標組件方法拋出的異常對象 @AfterThrowing(throwing="e",pointcut="within(* controller..*)") public void excute(Exception e){ //將異常信息寫入文件中 System.out.println("發生異常:"+e.getMessage()); FileWriter fw; try { fw = new FileWriter("D:note_error.log",true); PrintWriter pw=new PrintWriter(fw); //利用pw對象寫信息 Date time=new Date(); SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String str=sdf.format(time); pw.println("***************************"); pw.println("異常類型:"+e); pw.println("發生時間:"+str); pw.println("異常詳情:"); e.printStackTrace(pw); pw.close(); fw.close(); } catch (IOException e1) { // TODO Auto-generated catch block System.out.println("記錄異常失敗"); } } }
1. 關於什麼是事務,能夠參考個人另外一篇博客JDBC,而關於Spring中的事務管理詳細參考Spring事務管理函數
<context:property-placeholder location="classpath:conf/db.properties"/> <bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${jdbc.driver}"></property> <property name="url" value="${jdbc.url}"></property> <property name="password" value="${jdbc.password}"></property> <property name="username" value="${jdbc.name}"></property> </bean> <!--Spring事務管理--> <!--1.定義事務管理Bean--> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="ds"></property><!--注意,該行標籤指定數據源--> </bean> <!--2.經過配置將txManager做用到Service方法上--> <!--開啓@Transactional標記,使用該標記就表示在方法上使用txManager所表明的加強類--> <tx:annotation-driven transaction-manager="txManager"/>
<context:property-placeholder location="classpath:conf/db.properties"/> <bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${jdbc.driver}"></property> <property name="url" value="${jdbc.url}"></property> <property name="password" value="${jdbc.password}"></property> <property name="username" value="${jdbc.name}"></property> </bean> <!-- 事務管理配置 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="datasource"></property> </bean> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 傳播行爲 --> <tx:method name="save*" propagation="REQUIRED"/> <tx:method name="insert*" propagation="REQUIRED"/> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> <tx:method name="find*" propagation="SUPPORTS" read-only="true"/> </tx:attributes> </tx:advice> <!-- AOP配置 --> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* service.*.*(..))"/> </aop:config>