Aop面向切面
2021/6/27 23:50:39
本文主要是介绍Aop面向切面,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Aop面向切面
1.AOP在spring中的作用
1.横切关注点:跨越应用程序多个模块的方法或者功能,即使与我们的业务逻辑 无关但是我们需要关注的部分就是横切关注点,例如日志,安全。缓存,事务等等;
2.切面(ASPECT):横切关注点,被模块化的特殊对象,也就是一个类;
3.通知(ADVICE):切面必须要完成的工作,也就是类中的一个方法;
4.目标(TARGET):被通知的对象;
5.代理(Proxy):向目标对象应用通知之后创建对象;
6.切入点(PointCut):切面通知执行的“地点”的定义;
7.连接点(JointPoint):与切面匹配的执行点。
2.自定义AOP
2.1真实角色类
package fyjz.com.SpringAOP05; /* *真实角色(房东) */ public class Host implements Rent{ @Override public void rent() { System.out.println("我要把房子租出去"); } }
2.2抽象角色接口
package fyjz.com.SpringAOP05; /* * 抽象角色(租房) */ public interface Rent { void rent(); }
2.3AOP切面类
package fyjz.com.SpringAOP05; /* * AOP切面 */ public class DiyPointCut { public void after(){ System.out.println("方法后执行。。。"); } public void before(){ System.out.println("方法前执行。。。"); } }
2.4XML配置文件
<bean id="diy" class="fyjz.com.SpringAOP05.DiyPointCut"/> <bean id="host" class="fyjz.com.SpringAOP05.Host"/> <!--用Spring来管理AOP切面--> <aop:config> <!--把自定义的切面注入进来--> <aop:aspect ref="diy"> <!--切入点 expression:要执行的位置 expression="execution(该切入点的方法的修饰词 该切入点的包名.类名 该切入点的方法名(参数类型))": 如果要写参数列表则是该参数的全称(包名.类名) --> <aop:pointcut expression="execution(* fyjz.com.SpringAOP05.Host.*(..))" id="point"/> <!--通知(在切入点之前执行before 在切入点 之后执行after)--> <aop:after method="after" pointcut-ref="point"/> <aop:before method="before" pointcut-ref="point"/> </aop:aspect> </aop:config>
2.5Test测试类
注意:Aop基于接口生成动态代理,不是基于类生成动态代理的
public class TestDemo01 { @Test public void test01(){ ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); Rent r=(Rent)ac.getBean("host"); r.rent(); } }
2.6执行结果
方法前执行。。。 我要把房子租出去 方法后执行。。。
3.注解方式AOP
3.1.XML配置文件
<!--开启AOP驱动注解--> <!-- proxy-target-class:false jdk动态代理 proxy-target-class:true cglib动态代理 --> <aop:aspectj-autoproxy/> <!--让容器管理有标记的对象--> <context:component-scan base-package="fyjz.com.SpringAOP07"/>
3.2.真实角色类
package fyjz.com.SpringAOP07; import org.springframework.stereotype.Component; /* * 真实角色 */ @Component public class ServiceImpl implements Service{ @Override public void add() { System.out.println("增加业务"); } @Override public void delete() { // TODO Auto-generated method stub System.out.println("删除业务"); } @Override public void update() { // TODO Auto-generated method stub System.out.println("修改业务"); } @Override public void select() { // TODO Auto-generated method stub System.out.println("查询业务"); } }
3.3Test测试类
@Test public void test03(){ ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext3.xml"); Service s=(Service)ac.getBean("serviceImpl"); s.delete();
3.4.前置,后置通知
@Component:这是一个标记,容器会识别带有标记的这个类然后去管理由这个类生成的对象
@Aspect:证明这是一个切面,实际上这个切面已经注入到容器中了
前置通知:在切点前执行该方法
后置通知:在切点后执行该方法
package fyjz.com.SpringAOP07; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; /* * 切面 */ @Component @Aspect public class PointCut { //前置通知 @Before("execution(* fyjz.com.SpringAOP07.ServiceImpl.*(..))") public void after(){ System.out.println("方法前执行"); } //后置通知 @After("execution(* fyjz.com.SpringAOP07.ServiceImpl.*(..))") public void before(){ System.out.println("方法后执行"); } }
前置后置同时切入,则会执行出以下结果
方法前执行 删除业务 方法后执行
3.5环绕通知
环绕通知:在环绕通知增强中,我们可以给定一个参数代表我们要获取处理切入的点
package fyjz.com.SpringAOP07; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; /* * 切面 */ @Component @Aspect public class PointCut { //环绕通知 //@Around("execution(* fyjz.com.SpringAOP07.ServiceImpl.delete(..))") public void abroub(ProceedingJoinPoint jp) throws Throwable{ System.out.println("--环绕通知--"); jp.proceed();//执行切入点的方法 System.out.println("--环绕后通知--"); } }
结果如下:
--环绕通知-- 删除业务 --环绕后通知--
3.6前置,后置,环绕通知比较
//前置通知 @Before("execution(* fyjz.com.SpringAOP07.ServiceImpl.*(..))") public void after(){ System.out.println("方法前执行"); } //后置通知 @After("execution(* fyjz.com.SpringAOP07.ServiceImpl.*(..))") public void before(){ System.out.println("方法后执行"); } //环绕通知 @Around("execution(* fyjz.com.SpringAOP07.ServiceImpl.delete(..))") public void abroub(ProceedingJoinPoint jp) throws Throwable{ System.out.println("--环绕通知--"); jp.proceed();//执行切入点的方法 System.out.println("--环绕后通知--"); }
我们让后置,前置,以及环绕通知同时切入 ,则会发生一下结果:
--环绕通知-- 方法前执行 删除业务 --环绕后通知-- 方法后执行
可以看出:后置通知总是最后执行的
3.7异常捕获
切入点发生异常时,被@AfterThrowing捕获
//异常捕获 @AfterThrowing("execution(* fyjz.com.SpringAOP07.ServiceImpl.delete(..))") public void afterthrowing(){//不能带参数 System.out.println("发生异常了"); }
如果我们修改一下delete方法让其出错,那么该方法会捕获到异常
如:
@Override public void delete() { String s=""; char c=s.charAt(2); // TODO Auto-generated method stub System.out.println("删除业务"); }
结果如下:
发生异常了
这篇关于Aop面向切面的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南