ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Aop面向切面

2021-06-27 23:34:15  阅读:138  来源: 互联网

标签:-- void System 面向 Aop println out public 切面


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("删除业务");
	}

结果如下:

发生异常了

标签:--,void,System,面向,Aop,println,out,public,切面
来源: https://blog.csdn.net/weixin_47600732/article/details/118281901

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有