Spring----aop(面向切面编程)
为什么要使用AOP(面向切面编程)
在我们整个程序中,通常都有一些公共的代码,反反复复需要我们去写,而aop简单来说就是为我们处理这些公共的代码(专心做事),将之从程序中剥离出来,统一交由spring容器来处理,而我们则只需要将业务逻辑处理好就可以了。
AOP的原理
1.将复杂的需求分解出不同方面,将散布在系统中的公共功能集中解决
2.采用代理机制组装起来运行,在不改变原程序的基础上对代码段进行增强处理,增加新的功能。
AOP如何为我们处理这些公共代码呢?
有以下几种方式:
1.前置增强(目标方法执行前)
2.后置增强(目标方法执行后)
3.环绕增强(相当于前置增强和后置增强一起使用)
4.异常抛出增强(目标方法抛出异常时执行)
5.最终增强(相当于try-cache中的finally,如论以上4中增强执行了哪些,最终增强都会执行)
aop设计单元
切面(aspect):横切关注点而被模块化的类,称之为切面
通知(advice):切面要完成的工作,具体指切面类中的某个方法
连接点(joinpoint):一个应用再执行过程中能被插入切面的一个点
切点(pointcut):通配表达式,能被匹配一个或则多个连接点
织入(weaving):将切面应用到目标对象的代理对象的过程
顾问(adviscor):顾问就是通知,但是顾问又要比通知强大,通知是切面中的所有方法,而顾问则可以指定到某一个方法中
多说无益,上代码:
创建业务类
1 public class DoSome { 2 public void dosome(){ 3 System.out.println("我是service层"); 4 } 5 //该方法为了对比最终增强和后置增强的效果,还有就是异常抛出增强的效果 6 public void error(){ 7 int result=5/0;//伪造一个异常 8 System.out.println("我是异常方法"); 9 } 10 }
创建通知类(切面)
1 public class Advice{ 2 //前置增强 3 public void before(JoinPoint jp){ 4 System.out.println("我是方法"+jp.getSignature().getName()+"的前置增强!"); 5 } 6 //后置增强 7 public void afterReturning(JoinPoint jp,Object obj){ 8 System.out.println("我是方法"+jp.getSignature().getName()+"的后置增强!"+",返回值为"+obj); 9 } 10 //环绕增强 11 public void around(ProceedingJoinPoint jp) throws Throwable { 12 System.out.println("我是环绕增强中的前置增强!"); 13 Object proceed = jp.proceed();//植入目标方法 14 System.out.println("我是环绕增强中的后置增强!"); 15 } 16 //异常抛出增强 17 public void error(JoinPoint jp,Exception e){ 18 System.out.println("我是异常抛出增强"+",异常为:"+e.getMessage()); 19 } 20 //最终增强 21 public void after(JoinPoint jp){ 22 System.out.println("我是最终增强"); 23 } 24 }
配置核心配置文件applicationContext.xml
<!--创建业务类bean对象--> <bean id="service" class="com.cn.service.DoSome"></bean> <!--创建通知(切面)类的bean对象--> <bean id="advice" class="com.cn.advice.Advice"/> <!--对业务类进行增强--> <aop:config> <!--创建切点--> <aop:pointcut id="pointcut" expression="execution(public void *(..))"></aop:pointcut> <!--植入增强方法--> <aop:aspect id="aspect" ref="advice"> <aop:before method="before" pointcut-ref="pointcut"/> <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="obj"/> <aop:around method="around" pointcut-ref="pointcut"/> <aop:after-throwing method="error" pointcut-ref="pointcut" throwing="e"/> <aop:after method="after" pointcut-ref="pointcut"/> </aop:aspect> </aop:config>
创建测试类
1 public class App 2 { 3 public static void main( String[] args ) 4 { 5 ApplicationContext ac=new ClassPathXmlApplicationContext("/applicationContext.xml"); 6 DoSome bean = ac.getBean(DoSome.class); 7 //bean.dosome(); 8 bean.error(); 9 } 10 }
自行测试,在下就不发截图了
还有就是需要的pom节点
1 <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> 2 <dependency> 3 <groupId>org.springframework</groupId> 4 <artifactId>spring-context</artifactId> 5 <version>5.1.0.RELEASE</version> 6 </dependency> 7 <!-- https://mvnrepository.com/artifact/org.springframework/spring-core --> 8 <dependency> 9 <groupId>org.springframework</groupId> 10 <artifactId>spring-core</artifactId> 11 <version>5.1.0.RELEASE</version> 12 </dependency> 13 <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans --> 14 <dependency> 15 <groupId>org.springframework</groupId> 16 <artifactId>spring-beans</artifactId> 17 <version>5.1.0.RELEASE</version> 18 </dependency> 19 <!-- https://mvnrepository.com/artifact/org.springframework/spring-expression --> 20 <dependency> 21 <groupId>org.springframework</groupId> 22 <artifactId>spring-expression</artifactId> 23 <version>5.1.0.RELEASE</version> 24 </dependency> 25 <!--以上4个是spring的核心--> 26 <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> 27 <dependency> 28 <groupId>org.aspectj</groupId> 29 <artifactId>aspectjweaver</artifactId> 30 <version>1.9.2</version> 31 </dependency> 32 <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt --> 33 <dependency> 34 <groupId>org.aspectj</groupId> 35 <artifactId>aspectjrt</artifactId> 36 <version>1.9.2</version> 37 </dependency>
aspectj是aop的一个工具增强方法中的JoinPoint对象是由aspectj提供
当然,实现业务增强的方法不光这一种,我们还可以实现接口从写对应的方法
前置增强(MethodBeforeAdvice)后置增强(AfterReturningAdvice)环绕增强(MethodInterceptor)异常抛出增强(ThrowsAdvice)