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>