一,AOP介绍
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率
1,主要功能
日志记录,性能统计,安全控制,事务处理,异常处理等等
2,主要意图
将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码
3,AOP在Spring中的作用
提供声明式事务;允许用户自定义切面
横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 ....
切面(ASPECT) | 横切关注点 被模块化 的特殊对象,即,它是一个类 |
通知(Advice) | 切面必须要完成的工作。即,它是类中的一个方法 |
目标(Target) | 被通知对象 |
代理(Proxy) | 向目标对象应用通知之后创建的对象 |
切入点(PointCut) | 切面通知 执行的 “地点”的定义 |
连接点(JointPoint) | 与切入点匹配的执行点 |
二,使用SpringAPI实现AOP
1,接口(User)
1 //抽象角色 2 public interface User { 3 4 public void show(); 5 6 }
2,实现类(UserImpl)
1 //真实角色 2 public class UserImpl implements User{ 3 4 public void show() { 5 System.out.println("这是一个show方法"); 6 } 7 8 }
3,定义日志增加类实现
1.Log
1 import org.springframework.aop.MethodBeforeAdvice; 2 import java.lang.reflect.Method; 3 4 public class Log implements MethodBeforeAdvice { 5 6 //method:被调用目标对象的方法 7 //args:要被调用的方法的参数 8 //target:被调用的目标对象 9 public void before(Method method, Object[] args, Object target) throws Throwable { 10 System.out.println("目标对象:"+target.getClass().getName()+"的" 11 +method.getName()+"方法被执行了"); 12 } 13 }
2.AfterLog
1 import org.springframework.aop.AfterReturningAdvice; 2 import java.lang.reflect.Method; 3 4 public class AfterLog implements AfterReturningAdvice { 5 6 //returnValue : 返回值 7 //method : 被调用目标对象的方法 8 //args : 要被调用的方法的参数 9 //target : 被调用的目标对象 10 11 public void afterReturning(Object returnValue, Method method, 12 Object[] args, Object target) throws Throwable { 13 System.out.println("执行了目标对象:"+target.getClass().getName()+"的" 14 +method.getName()+"方法,返回值:"+returnValue); 15 } 16 17 }
4,编写Spring核心配置文件(logbeans.xml)
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" 4 xmlns:aop="http://www.springframework.org/schema/aop" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://www.springframework.org/schema/aop 8 http://www.springframework.org/schema/aop/spring-aop.xsd"> 9 10 <!--注册bean--> 11 <bean id="User" class="service.UserImpl"/> 12 13 <!--注册日志的bean--> 14 <bean id="Log" class="log.Log"/> 15 <bean id="AfterLog" class="log.AfterLog"/> 16 17 <!--使用spring的AOP切入--> 18 <aop:config> 19 <!--切入点--> 20 <aop:pointcut id="pointcut" expression="execution(* service.UserImpl.*(..))"/> 21 <!--执行通知,增强--> 22 <aop:advisor advice-ref="Log" pointcut-ref="pointcut"/> 23 <aop:advisor advice-ref="AfterLog" pointcut-ref="pointcut"/> 24 </aop:config> 25 26 </beans>
【注意点】
5,编写测试类(AopTest)
1 public class AopTest { 2 @Test 3 public void Test01(){ 4 ClassPathXmlApplicationContext context = 5 new ClassPathXmlApplicationContext("logbeans.xml"); 6 User user = (User) context.getBean("User"); 7 8 user.show(); 9 } 10 }
【注意点:测试时需要导入AOP的包在你的pom.xml中】
1 <dependency> 2 <groupId>org.aspectj</groupId> 3 <artifactId>aspectjweaver</artifactId> 4 <version>1.8.9</version> 5 </dependency>
6,运行结果
三,自定义类实现AOP
和使用SpringAPI实现AOP一样,先要建立抽象角色和真实角色,我们这里的接口与实体类和前面一样
1,自定一个Aop增强类:也就是所谓的切面
1 public class Diy { 2 3 public void before(){ 4 System.out.println("show方法执行前"); 5 } 6 7 public void after(){ 8 System.out.println("show方法执行后"); 9 } 10 }
2,配置文件(diybeans.xml)
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" 4 xmlns:aop="http://www.springframework.org/schema/aop" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://www.springframework.org/schema/aop 8 http://www.springframework.org/schema/aop/spring-aop.xsd"> 9 10 <!--注册bean--> 11 <bean id="User" class="service.UserImpl"/> 12 13 <!--自定义的AOP增强类--> 14 <bean id="Diy" class="diy.Diy"/> 15 16 <!--编写aop配置文件--> 17 <aop:config> 18 19 <!--切面--> 20 <aop:aspect ref="Diy"> 21 <!--切入点--> 22 <aop:pointcut id="diyPointCut" expression="execution(* service.UserImpl.*(..))"/> 23 <aop:before method="before" pointcut-ref="diyPointCut"/> 24 <aop:after method="after" pointcut-ref="diyPointCut"/> 25 </aop:aspect> 26 27 </aop:config> 28 29 </beans>
3,测试类
1 public class AopTest { 2 @Test 3 public void Test02(){ 4 ClassPathXmlApplicationContext context = 5 new ClassPathXmlApplicationContext("diybeans.xml"); 6 User user = (User) context.getBean("User"); 7 8 user.show(); 9 } 10 }
4,运行结果
四,使用注解实现AOP
接口和实体类不变
1,编写AOP增强类
1 @Aspect 2 public class Anno { 3 4 @Before("execution(* service.UserImpl.*(..))") 5 public void before(){ 6 System.out.println("show方法执行前"); 7 } 8 9 @After("execution(* service.UserImpl.*(..))") 10 public void after(){ 11 System.out.println("show方法执行后"); 12 } 13 14 }
【注意点】
2,配置文件(annobeans.xml)
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" 4 xmlns:aop="http://www.springframework.org/schema/aop" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://www.springframework.org/schema/aop 8 http://www.springframework.org/schema/aop/spring-aop.xsd"> 9 10 <!--注册bean--> 11 <bean id="User" class="service.UserImpl"/> 12 13 <!--注册日志的bean--> 14 <bean id="Log" class="log.Log"/> 15 <bean id="AfterLog" class="log.AfterLog"/> 16 17 <!--使用spring的AOP切入--> 18 <aop:config> 19 <!--切入点--> 20 <aop:pointcut id="pointcut" expression="execution(* service.UserImpl.*(..))"/> 21 <!--执行通知,增强--> 22 <aop:advisor advice-ref="Log" pointcut-ref="pointcut"/> 23 <aop:advisor advice-ref="AfterLog" pointcut-ref="pointcut"/> 24 </aop:config> 25 26 </beans>
3,测试类
1 public class AopTest { 2 @Test 3 public void Test03(){ 4 ClassPathXmlApplicationContext context = 5 new ClassPathXmlApplicationContext("annobeans.xml"); 6 User user = (User) context.getBean("User"); 7 8 user.show(); 9 } 10 }
4,运行结果
五,AOP小结
- 本质就是动态代理
- 需要到一个包,用来进行aop织入的包: aspectjweaver
- 注意别遗漏了切面
- 三种实现AOP的方法
- 使用SpringAPI来实现AOP
- 使用自定义类来实现AOP
- 使用注解实现AOP