摘要:
|
“自立”是自然对每个人的要求.也许你的父母、老师能够帮助你,其他人也可以帮助你,但是所有这些人都只是帮你更加自主、自立。
最近完结了有关于AOP相关知识的学习,接下来就给大家讲讲我对AOP的一些见解。
既然学习AOP大家知道AOP是什么嘛?那么就开始喽~
AOP(Aspect Oriented Programming):面向切面编程,也是一种变成思想。(静态角度)
OOP(Object Oriented Programming):面向对象编程。(动态代理:JDK动态代理 CGLIB动态代理)
代理模(Proxy):为其他对象提供一个代理以控制对这个对象的访问。
适合的场合:远程代理 虚拟代理 安全代理(只需要简单了解不做详解)
↑ ↑ ↑ ↑ ↑ ↑只是关于代理的图片展示稍后会有详细代码
基本术语(一些名词):
(1)切面(Aspect)
切面泛指[*交叉业务逻辑*]。事务处理和日志处理可以理解为切面。常用的切面有通知(Advice)与顾问(Advisor)。实际就是对主业务逻辑的一种增强。
(2)织入(Weaving)
织入是指将切面代码插入到目标对象的过程。代理的invoke方法完成的工作,可以称为织入。
(3) 连接点(JoinPoint)
连接点是指可以被切面织入的方法。通常业务接口的方法均为连接点
(4)切入点(PointCut)
切入点指切面具体织入的方法
注意:被标记为final的方法是不能作为连接点与切入点的。因为最终的是不能被修改的,不能被增强的。
(5)目标对象(Target)
目标对象指将要被增强的对象。即包含主业务逻辑的类的对象。
(6)通知(Advice)
通知是切面的一种实现,可以完成简单的织入功能。通知定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是执行之后执行等。切入点定义切入的位置,通知定义切入的时间。
(7)顾问(Advisor)
顾问是切面的另一种实现,能够将通知以更为复杂的方式织入到目标对象中,是将通知包装为更复杂切面的装配器。
Spring的经典AOP配置方案
1、使用的是Aspectj第三方框架,实现了AOP思想
2、注解配置的AOP
3、纯POJO 就是一个普通的类<aop:config>
接下来进入代码模式:
代码模式一:纯POJO(通过POJO来实现一个前置增强类)
定义一个简单的UserBiz类给它一个方法:
1 package cn.happy.biz; 2 3 public class UserBiz { 4 public void addStu(UserInf user){ 5 System.out.println("add ok"); 6 } 7 }
在aop包下BeforeAdvice前置增强类,它需要实现MethodBeforeAdvice接口的before方法:
1 import org.springframework.aop.MethodBeforeAdvice; 2 3 /** 4 * before 5 * 6 */ 7 public class BeforeAdvice implements MethodBeforeAdvice{ 8 9 /** 10 * 11 * @param method 被代理的目标的方法 12 * @param args 传递给目标方法的参数 13 * @param obj 被代理的目标对象 14 15 * @throws Throwable 16 */ 17 @Override 18 public void before(Method method, Object[] args , Object obj) 19 throws Throwable { 20 System.out.println("========before======"); 21 }
配置文件(注意引入的命名空间)<aop:config>配置下实现切面:
1 ...... 2 <bean id="biz" class="cn.happy.biz.UserBiz"></bean> 3 4 <!-- 前置 --> 5 <bean id="beforeAdvice" class="cn.happy.aop.BeforeAdvice"></bean> 6 <!-- aop配置切面 --> 7 <aop:config> 8 <!-- 定义切点 --> 9 <aop:pointcut expression="execution(public void *(cn.happy.biz.UserInf))" id="pointcut"/> 10 <!-- 增强处理和切点结合 --> 11 <aop:advisor advice-ref="beforeAdvice" pointcut-ref="pointcut"/> 12 <aop:advisor advice-ref="afterAdivice" pointcut-ref="pointcut"/> 13 </aop:config> 14 ......
测试类:
1 public void testOne(){ 2 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); 3 UserBiz biz = (UserBiz)ctx.getBean("biz"); 4 biz.addStu(new UserInf()); 5 6 }
=========================华丽的分割线==================================
用注解配置的AOP:前置通知,后置通知,返回通知,异常通知,环绕通知
定义一个接口:
1 public interface ISomeService { 2 //1.1 执行事务 3 public void doTransaction(); 4 //1.2 书写日志 5 public String doLog(); 6 }
实现接口的实现类:
1 public class SomeServiceImpl implements ISomeService { 2 3 public void doTransaction() { 4 System.out.println("开启事务"); 5 } 6 7 public String doLog() { 8 System.out.println("书写日志"+5/0); 9 return "我是书写日志的返回值哦!!!!!"; 10 } 11 12 }
增强类用注解写:
1 @Aspect 2 public class MyAspect { 3 //前置通知 4 @Before(value="execution(public * *(..))") 5 public void MyBefore(){ 6 System.out.println("这是前置通知哦!!!!!!!在执行目标对象之前执行"); 7 } 8 9 //后置通知 10 @AfterReturning(value="execution(public * *(..))") 11 public void MyAfterReturning(){ 12 System.out.println("这是后置通知哦!!!!!!!在执行目标对象之前执行"); 13 } 14 15 //环绕通知 16 /* @Around(value="execution(public * *(..))") 17 public void MyAround(ProceedingJoinPoint pjp){ 18 System.out.println("这是环绕通知前哦!!!!!!!在执行目标对象之前执行"); 19 try { 20 pjp.proceed(); 21 System.out.println("这是环绕通知后哦!!!!!!!在执行目标对象之前执行"); 22 } catch (Throwable e) { 23 // TODO Auto-generated catch block 24 e.printStackTrace(); 25 } 26 }*/ 27 28 //异常通知 29 @AfterThrowing(value="execution(public * *(..))") 30 public void MyAfterThrowing(){ 31 System.out.println("这是异常通知哦!!!!!!!在执行目标对象之前执行"); 32 } 33 34 //最终通知 35 @After(value="execution(public * *(..))") 36 public void MyAfter(){ 37 System.out.println("这是最终通知哦!!!!!!!在执行目标对象之前执行"); 38 } 39 }
配置文件:
1 <!-- 目标对象 --> 2 <bean id="someService" class="cn.happy.enetity.SomeServiceImpl"></bean> 3 4 <!-- 切面: --> 5 <bean id="myAspect" class="cn.happy.aspece.MyAspect"></bean> 6 <!--aop:aspectj可以启动对@AspectJ注解支持--> 7 <aop:aspectj-autoproxy/> 8 </beans>
测试类:
1 public void testOne(){ 2 3 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); 4 ISomeService service = (ISomeService)ctx.getBean("someService"); 5 service.doTransaction(); 6 String result = service.doLog(); 7 System.out.println(result); 8 }
=========================华丽的分割线==================================
使用的是Aspectj第三方框架,实现了AOP思想XML的方式(就是一个普通类通过配置实现 )
定义一个接口:
1 public interface ISomeService { 2 //1.1 执行事务 3 public void doTransaction(); 4 //1.2 书写日志 5 public String doLog(); 6 }
实现类:
1 public class SomeServiceImpl implements ISomeService { 2 3 public void doTransaction() { 4 System.out.println("开启事务"); 5 } 6 7 public String doLog() { 8 /*System.out.println("书写日志"+5/0);*/ 9 System.out.println("书写日志"); 10 return "我是书写日志的返回值哦!!!!!"; 11 } 12 13 }
定一个增强类就是一个普通类通过配置实现 :
1 public class MyAspect { 2 // 前置通知execution(public * *(..)) 3 public void MyBefore() { 4 System.out.println("这是前置通知哦!!!!!!!在执行目标对象之前执行"); 5 } 6 7 // 后置通知execution(public * *(..)) 8 public void MyAfterReturning() { 9 System.out.println("这是后置通知哦!!!!!!!在执行目标对象之前执行"); 10 } 11 12 // 异常通知 13 public void MyAfterThrowing() { 14 System.out.println("这是异常通知哦!!!!!!!在执行目标对象之前执行"); 15 } 16 17 // 最终通知 18 public void MyAfter() { 19 System.out.println("这是最终通知哦!!!!!!!在执行目标对象之前执行"); 20 } 21 22 //环绕通知 23 public String MyAround(ProceedingJoinPoint pjp){ 24 System.out.println("这是环绕通知前哦!!!!!!!在执行目标对象之前执行"); 25 try { 26 Object result=pjp.proceed(); 27 System.out.println("这是环绕通知后哦!!!!!!!在执行目标对象之前执行"); 28 } catch (Throwable e) { 29 // TODO Auto-generated catch block 30 e.printStackTrace(); 31 } 32 return "result"; 33 } 34 }
配置文件:
1 ...... 2 <!-- 目标对象 --> 3 <bean id="someService" class="enetity.SomeServiceImpl"></bean> 4 5 <!-- 切面: --> 6 <bean id="myAspect" class="aspece.MyAspect"></bean> 7 8 9 <!-- aop的配置 --> 10 <aop:config> 11 <!-- 切点 --> 12 <aop:pointcut expression="execution(public * *(..))" id="dopointcut"/> 13 <aop:aspect ref="myAspect"> 14 15 <aop:before method="MyBefore" pointcut-ref="dopointcut"/> 16 <aop:after-returning method="MyAfterReturning" pointcut-ref="dopointcut"/> 17 <!-- <aop:after-throwing method="MyAfterThrowing" pointcut-ref="dopointcut"/> --> 18 <aop:after method="MyAfter" pointcut-ref="dopointcut"/> 19 <aop:around method="MyAround" pointcut-ref="dopointcut"/> 20 </aop:aspect> 21 22 </aop:config> 23 </beans> 24 ......
测试类:
1 public void testOne(){ 2 3 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); 4 ISomeService service = (ISomeService)ctx.getBean("someService"); 5 service.doTransaction(); 6 String result = service.doLog(); 7 System.out.println(result); 8 }
以上就是我对AOP相关知识代码层面的讲解。学的不是很好,也是早上请教了同学才能更深一层了解AOP。就如文章开头:
“自立”是自然对每个人的要求.也许你的父母、老师能够帮助你,其他人也可以帮助你,但是所有这些人都只是帮你更加自主、自立。
希望可以鼓励那些在快学不下去的时候去请教下同学,老师...