AOP:全称是 Aspect Oriented Programming 即:面向切面编程。java
AOP技术是对OOP技术的一种延伸,AOP是面向纵向,OOP是面向横向。简单的说它就是把咱们程序重复的代码抽取出来,在须要执行的时候,使用动态代理的技术,在不修改源码的
基础上,对咱们的已有方法进行加强。mysql
做用:在程序运行期间,不修改源码对已有方法前面和后面进行加强。
优点:减小重复代码、提升开发效率、维护方便spring
使用动态代理技术sql
实现步骤以下express
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.6.RELEASE</version> </dependency> <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.6</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> 下面几个是必需要导的包 <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.2</version> </dependency> <dependency> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency>
package com.ithema.jdbc.dao; public class StudentDao { //在执行add方法以前执行日志 public int add(int a,int b){ System.out.println("执行了add方法"); return a+b; } public int jian(int a,int b){ System.out.println("执行了减法"); return a-b; } /* public void testexe(){ int i=10/0; }*/ }
package com.ithema.jdbc.aop; import org.apache.log4j.Logger; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import java.util.Arrays; /** * 切面: * 前置加强、后置加强、异常加强、最终加强、环绕加强 * * Spring aop彻底是用动态代理实现的 * 可是动态代理又有两种,jdkk代理,cglib代理(更强大一些) * spirng aop:默认使用jdk代理,可是你的目标类没接口,会自动切换到cglib代理 */ public class UserLogger { //在目标方法调用以前执行该方法 Logger logger=Logger.getLogger(UserLogger.class); public void before(JoinPoint jp){ logger.info("前置加强,目标类名"+jp.getTarget()+"里面的"+jp.getSignature().getName()+ "参数为:"+ Arrays.toString(jp.getArgs())); } //在目标方法调用以后执行该方法 //当方法抛出异常就不会执行了,全部该方法不适合作日志收集,由于发生了异常不执行该方法没法将日志保存下来 //全部后置加强用的不多 public void after(JoinPoint jp,Object result){ logger.info("后置加强,执行完类"+jp.getTarget()+"里面的"+jp.getSignature().getName()+ "方法,结果为:"+ result); } //在方法抛出异常后就会加强、没有异常就不会执行、若是用户try-catch,也不会加强 //执行错误的话,很是适合该加强(异常加强) //Java异常体系,根类是Throwable public void afterThorwing(JoinPoint jp,Throwable e){ logger.info("异常加强,执行类"+jp.getTarget()+"里面的"+jp.getSignature().getName()+ "方法抛出异常:"+e.getMessage()); } //最终加强:不管是否有异常,都会执行,相似与finally,能够或者是认为是后置加强的升级版 public void finalafter(JoinPoint jp){ logger.info("最终加强:执行完类"+jp.getTarget()+"里面的"+jp.getSignature().getName()); } //环绕加强,集合了前置添加后置,而且更增强大、当执行方法发生异常后面的就不执行了 //一、能够修改方法的参数 二、也能够修改方法的返回值( return result) public Object around(ProceedingJoinPoint jp)throws Throwable{ Object [] args=jp.getArgs();//获取方法参数 //能够修改方法的参数 //args = new Object[]{20,1}; logger.info("环绕加强:方法为:"+jp.getArgs()); Object result=jp.proceed();//执行目标方法 //也能够修改方法的返回值 //return 100; return result; } }
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" 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/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--一个bean就是一个对象> <bean id="studentDao" class="com.ithema.jdbc.dao.StudentDao"> </bean> <bean id="userLogger" class="com.ithema.jdbc.aop.UserLogger"> </bean>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" 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/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="studentDao" class="com.ithema.jdbc.dao.StudentDao"> </bean> <bean id="userLogger" class="com.ithema.jdbc.aop.UserLogger"> </bean> <!--aop配置,实现dao里面的方法先后加强--> <aop:config> <!--定义切入点--> <!--标准写法格式:(返回值:全类名(包名.类名.方法名(参数类型列表))--> <aop:pointcut id="pointcut" expression="execution(* com.ithema.jdbc..*.*(..))"></aop:pointcut> <!--组织加强--> <!--切面ref:应用其余bean对象--> <aop:aspect ref="userLogger"> <aop:before method="before" pointcut-ref="pointcut"></aop:before> <aop:after-returning method="after" pointcut-ref="pointcut" returning="result"></aop:after-returning> <aop:after-throwing method="afterThorwing" pointcut-ref="pointcut" throwing="e"></aop:after-throwing> <aop:after method="finalafter" pointcut-ref="pointcut"></aop:after> <aop:around method="around" pointcut-ref="pointcut"></aop:around> </aop:aspect> </aop:config> </beans>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.6.RELEASE</version> </dependency> <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.6</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> 下面几个是必需要导的包 <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.2</version> </dependency> <dependency> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--告诉Spring容器在建立的时候要扫描包,配置所须要的标签不在bean约束中,而是 在一个叫作context的空降名称和约束中--> <context:component-scan base-package="com.bdqn"></context:component-scan> <!-- 开启注解aop--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
package com.bdqn.aop; import org.apache.log4j.Logger; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; import java.util.Arrays; @Component @Aspect public class UserLogger { //在目标方法调用以前执行该方法 Logger logger=Logger.getLogger(UserLogger.class); //定义切点 @Pointcut("execution(* com.bdqn.aop..*.*(..))") public void pointcut(){} @Before("pointcut()") public void before(JoinPoint jp){ logger.info("前置加强,目标类名"+jp.getTarget()+"里面的"+jp.getSignature().getName()+ "参数为:"+ Arrays.toString(jp.getArgs())); } //在目标方法调用以后执行该方法 //当方法抛出异常就不会执行了,全部该方法不适合作日志收集,由于发生了异常不执行该方法没法将日志保存下来 //全部后置加强用的不多 public void after(JoinPoint jp,Object result){ logger.info("后置加强,执行完类"+jp.getTarget()+"里面的"+jp.getSignature().getName()+ "方法,结果为:"+ result); } //在方法抛出异常后就会加强、没有异常就不会执行、若是用户try-catch,也不会加强 //执行错误的话,很是适合该加强(异常加强) //Java异常体系,根类是Throwable @AfterThrowing(pointcut = "execution(* com.bdqn.aop..*.*(..))",throwing = "e") public void afterThorwing(JoinPoint jp,Throwable e){ logger.info("异常加强,执行类"+jp.getTarget()+"里面的"+jp.getSignature().getName()+ "方法抛出异常:"+e.getMessage()); } //最终加强:不管是否有异常,都会执行,相似与finally,能够或者是认为是后置加强的升级版 @After("execution(* com.bdqn.aop..*.*(..))") public void finalafter(JoinPoint jp){ logger.info("最终加强:执行完类"+jp.getTarget()+"里面的"+jp.getSignature().getName()); } //环绕加强,集合了前置添加后置,而且更增强大、当执行方法发生异常后面的就不执行了 //一、能够修改方法的参数 二、也能够修改方法的返回值( return result) @Around("execution(* com.bdqn.aop..*.*(..))") public Object around(ProceedingJoinPoint jp)throws Throwable{ Object [] args=jp.getArgs();//获取方法参数 //能够修改方法的参数 //args = new Object[]{20,1}; logger.info("环绕加强:方法为:"+jp.getArgs()); Object result=jp.proceed();//执行目标方法 //也能够修改方法的返回值 //return 100; return result; } }
package com.bdqn.test; import com.bdqn.dao.StudentDao; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:ApplicationContext.xml") public class Testaop { @Autowired private StudentDao studentDao; @Test public void testaop(){ studentDao.add(); studentDao.jian(3,1); System.out.println("执行了减法,结果为:"); } }