1.AOP到底是什么?
Aspect Oriented Programing 面向切面编程
1.2.3.4代码不重复 不能向上抽取 不能纵向抽取
但是横向却可以抽取 将 业务和 监视事务分离
连接点(Joinpoint):连接点相当于方法,相当于数据库里的记录
切点(Pointcut):相当于数据库里的查询条件,一个切点对应多个连接点
增强(Advice):是织入目标类连接点上的一段代码,描述信息
目标对象(Target):增强织入的逻辑类引介(Introduction):特殊的增强,属性和方法
织人:是将增强添加到目标类具体连接点上的过程,
代理类(Proxy):AOP织入增强后,产生一个结果类它是融入原类和增强逻辑的代理类
切面(Aspect):切面是由切点和引介组成 ,将横切逻辑织入切面所指定的连接点
1.创建增强类
通过实现接口,在接口方法中定义横切逻辑,就可以将它们织人目标方法的相应连接点的位置
1.1 前置增强
1 package com.asm; 2 3 public interface Waiter { 4 void greetTo(String name); 5 6 void serveTo(String name); 7 }
1 public class NaiveWaiter implements Waiter { 2 3 public void greetTo(String name) { 4 System.out.println("greet to " + name + "..."); 5 } 6 7 public void serveTo(String name) { 8 System.out.println("serving " + name + "..."); 9 } 10 }
1 public class GreetingBeforeAdvice implements MethodBeforeAdvice{ 2 3 @Override 4 public void before(Method method, Object[] args, Object obj) 5 throws Throwable { 6 String clientName=(String)args[0]; 7 System.out.println("How are you mr,"+clientName+"."); 8 } 9 10 11 }
1 package com.asm; 2 3 import org.springframework.aop.BeforeAdvice; 4 import org.springframework.aop.framework.ProxyFactory; 5 import org.testng.annotations.BeforeTest; 6 import org.testng.annotations.Test; 7 8 public class BeforeAdviceTest { 9 10 private Waiter target; 11 private BeforeAdvice advice; 12 private ProxyFactory pf; 13 14 @BeforeTest 15 public void init() { 16 target = new NaiveWaiter(); 17 advice = new GreetingBeforeAdvice(); 18 //①Spring提供的代理工厂 19 pf = new ProxyFactory(); 20 // ②设置代理目标 21 pf.setTarget(target); 22 //③为代理目标添加增强 23 pf.addAdvice(advice); 24 } 25 26 @Test 27 public void beforeAdvice() { 28 Waiter proxy = (Waiter) pf.getProxy(); 29 proxy.greetTo("John"); 30 proxy.serveTo("Tom"); 31 } 32 }
在Spring配置增强
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 8 http://www.springframework.org/schema/context 9 http://www.springframework.org/schema/context/spring-context-3.1.xsd 10 http://www.springframework.org/schema/tx 11 http://www.springframework.org/schema/tx/spring-tx-3.1.xsd 12 http://www.springframework.org/schema/aop 13 http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"> 14 15 <!-- 扫描类包下的类 这样Spring定义的注解才能产生作用 16 如@Resposity @Autowired 17 --> 18 19 <!-- 需要代理的业务类 --> 20 <bean id="target" class="com.asm.NaiveWaiter"></bean> 21 <!-- 指定增强,一个业务类可以有多个增强形成增强链,调用顺序与添加顺序一致 --> 22 <bean id="greetAdvice" class="com.asm.GreetingBeforeAdvice"></bean> 23 <!-- 利用ProxyFactoryBean创建代理 --> 24 <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean" 25 p:proxyInterfaces="com.asm.Waiter" // 指定代理接口,多个用List 26 p:interceptorNames="greetAdvice" //指定增强 27 p:target-ref="target" //指定对哪个bean进行代理 28 /> 29 </beans>
1 package com.asm; 2 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 import org.testng.annotations.Test; 6 7 public class SpringTest1 { 8 9 public static void main(String[] args) { 10 11 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); 12 Waiter waiter = (Waiter) ctx.getBean("waiter"); 13 waiter.greetTo("join"); 14 } 15 }
后置增强:
1 public class GreetingAfterAdvice implements AfterReturningAdvice { 2 3 public void afterReturning(Object returnObj, Method method, Object[] args, 4 Object obj) throws Throwable { 5 System.out.println("Please enjoy yourself!"); 6 } 7 }
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 8 http://www.springframework.org/schema/context 9 http://www.springframework.org/schema/context/spring-context-3.1.xsd 10 http://www.springframework.org/schema/tx 11 http://www.springframework.org/schema/tx/spring-tx-3.1.xsd 12 http://www.springframework.org/schema/aop 13 http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"> 14 15 <!-- 扫描类包下的类 这样Spring定义的注解才能产生作用 16 如@Resposity @Autowired 17 --> 18 19 <!-- 需要代理的业务类 --> 20 <bean id="target" class="com.asm.NaiveWaiter"></bean> 21 <!-- 指定增强,一个业务类可以有多个增强形成增强链,调用顺序与添加顺序一致 --> 22 <bean id="greetBefore" class="com.asm.GreetingBeforeAdvice"> 23 </bean> 24 <bean id="greetAfter" class="com.asm.GreetingAfterAdvice"> 25 </bean> 26 <!-- 利用ProxyFactoryBean创建代理 --> 27 <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean" 28 p:proxyInterfaces="com.asm.Waiter" 29 p:interceptorNames="greetBefore,greetingAfter" 30 p:target-ref="target" 31 /> 32 </beans>
环绕增强:
1 package com.smart.advice; 2 3 import org.aopalliance.intercept.MethodInterceptor; 4 import org.aopalliance.intercept.MethodInvocation; 5 6 public class GreetingInterceptor implements MethodInterceptor { 7 8 public Object invoke(MethodInvocation invocation) throws Throwable { 9 Object[] args = invocation.getArguments(); 10 String clientName = (String) args[0]; 11 System.out.println("How are you!Mr." + clientName + "."); 12 13 Object obj = invocation.proceed(); 14 15 System.out.println("Please enjoy yourself!"); 16 17 return obj; 18 } 19 }
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 8 http://www.springframework.org/schema/context 9 http://www.springframework.org/schema/context/spring-context-3.1.xsd 10 http://www.springframework.org/schema/tx 11 http://www.springframework.org/schema/tx/spring-tx-3.1.xsd 12 http://www.springframework.org/schema/aop 13 http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"> 14 15 <!-- 扫描类包下的类 这样Spring定义的注解才能产生作用 16 如@Resposity @Autowired 17 --> 18 19 <!-- 需要代理的业务类 --> 20 <bean id="target" class="com.asm.NaiveWaiter"></bean> 21 <!-- 指定增强,一个业务类可以有多个增强形成增强链,调用顺序与添加顺序一致 --> 22 <bean id="greetAdvice" class="com.asm.GreetingInterceptor "></bean> 23 <!-- 利用ProxyFactoryBean创建代理 --> 24 <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean" 25 p:proxyInterfaces="com.asm.Waiter" 26 p:interceptorNames="greetAdvice" 27 p:target-ref="target" 28 /> 29 </beans>
异常增强:
1 public class TransactionManager implements ThrowsAdvice { 2 3 4 public void afterThrowing(Method method, Object[] args, Object target, 5 Exception ex) throws Throwable { 6 ex = null; 7 System.out.println("-----------"); 8 System.out.println("method:" + method.getName()); 9 //System.out.println("抛出异常:" + ex.getMessage()); 10 System.out.println("成功回滚事务。"); 11 } 12 }
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 8 http://www.springframework.org/schema/context 9 http://www.springframework.org/schema/context/spring-context-3.1.xsd 10 http://www.springframework.org/schema/tx 11 http://www.springframework.org/schema/tx/spring-tx-3.1.xsd 12 http://www.springframework.org/schema/aop 13 http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"> 14 15 <!-- 扫描类包下的类 这样Spring定义的注解才能产生作用 16 如@Resposity @Autowired 17 --> 18 19 <!-- 需要代理的业务类 --> 20 <bean id="target" class="com.asm.NaiveWaiter"></bean> 21 <!-- 指定增强,一个业务类可以有多个增强形成增强链,调用顺序与添加顺序一致 --> 22 <bean id="transactionManager" class="com.asm.TransactionManager "></bean> 23 <!-- 利用ProxyFactoryBean创建代理 --> 24 <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean" 25 p:proxyInterfaces="com.asm.Waiter" 26 p:interceptorNames="greetAdvice" 27 p:target-ref="target" 28 p:proxyTargetClass="true" //CGLIB代理 29 /> 30 </beans>
spring目前支持5种类型增强:
-
前置增强:org.springframework.aop.BeforeAdvice 代表前置增强,因为spring只支持方法级的增强,所以MethodBeforeAdvice是目前可用的前置增强,表示在目标方法执行前实施增强,而 BeforeAdvice是为了将来版本扩展需要而定义的。
-
后置增强:org.springframework.aop.AfterReturningAdvice代表后增强,表示在目标方法执行后实施增强。
-
环绕增强:org.aopalliance.intercept.MethodInterceptor代表环绕增强,表示在目标方法执行前后实施增强。
-
异常抛出增强:org.springframework.aop.ThrowsAdvice代表抛出异常增强,表示在目标方法抛出异常后实施增强。
-
引介增强:org.springframework.aop.IntroductionInterceptor代表引介增强,表示在目标类中添加一些新的方法和属性。