SpringAOP(面向切面编程)

官方概念: AOP,即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系。
例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

个人理解:
1.首先,AOP是OOP面向对象开发的扩展补充:面向切面编程。因为正常开发流程中为OOP纵向开发,由dao-service-servlet-web,当我们需要对其中一个模块进行添加其他额外功能时,此时为横向开发,已经不适用于使用OOP思想开发。为了不修改原有代码,减小耦合性,便使用到了AOP横向开发。他将需要扩展的定义为一个切面,对其进行添加想要的功能。
2.在实现面向切面编程中,使用了代理模式,代理模式是将要扩展的功能交给代理对象来操作。
首先要使用反射包中的InvocationHandler:用来执行代理对象的方法 Proxy:用来获取代理实例
(而Spring对AOP提供了支持,Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理)

在这里插入图片描述

 

 Spring对AOP的支持


Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。因此,AOP代理可以直接使用容器中的其它bean实例作为目标,这种关系可由IOC容器的依赖注入提供。
Spring创建代理的规则为:
1、默认使用Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了
2、当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIB
AOP编程其实是很简单的事情,纵观AOP编程,程序员只需要参与三个部分:

  1. 定义普通业务组件
  2. 定义切入点,一个切入点可能横切多个业务组件
  3. 定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作

所以进行AOP编程的关键就是定义切入点和定义增强处理,一旦定义了合适的切入点和增强处理,AOP框架将自动生成AOP代理,即:代理对象的方法=增强处理+被代理对象的方法。

 Aop在Spring中的作用

提供声明式事务;允许用户自定义切面
横切关注点: 跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志,安全,缓存,事务等等
切面(ASPECT) : 横切关注点被模块化的特殊对象。即,它是一个类。
通知(Advice) : 切面必须要完成的工作。即,它是类中的一个方法
目标(Target) : 被通知对象
代理(Proxy) : 向目标对象应用通知之后创建的对象
切入点(PointCut) : 切面通知执行的"地点"的定义。
连接点(JointPoint) : 与切入点匹配的执行点

在这里插入图片描述

 


Aop实现方式

注意:使用AOP织入,需要导入依赖包

<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.4</version>
</dependency>

方式一:使用Spring API接口

<--方式一:使用原生:Spring API接口1-->
<!--配置aop:需要导入aop的约束-->
<aop:config>
     <!--切入点:expression:表达式execution( 要执行的位置! *****-->
<aop:pointcut id=" pointcut" expression="execution(* com.kuang.service.UserServiceImp1.*(..))"/>
     <!--执行环绕增加! -->
<aop:advisor advice-ref="log" pointcut-ref=" pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>

方式二:自定义来实现AOP

自定义的类:
public class DiyPointCut {
    public void before( ){
        System. out . print1n("=======方法执行前========");
    }
    public void |after(){
        System. out . print1n("=======方法执行后========");
    }
}
<!--自定义类-->
<bean id="diy" class="com. kuang. diy.DiyPointCut"/>
<aop :config>
        <!--自定义切面,ref 要引用的类-->
<aop:aspect ref="diy">
        <!--切入点-->
<aop:pointcut id=" point" expression=" execution(*com.kuang.service.UserServiceImp1.*(..))"/>
        <!--通知-->
<aop: before method= "before" pointcut-ref="point"/>
<aop:after method="after" pointcut -ref="point"/>
</aop:aspect>
</aop : config>

方式三:使用注解实现

@Aspect //标注这个类是一个 切面
    public class AnnotationPointCut {
        @Before("execution(* com. kuang. service.UserServiceImp1.*(..))")
        public void before(){
            System. out. println("=====方法执行前=====");
        }
        @After("execution(* com. kuang. service . UserServiceImp1.*(..))")
        public void after(){
            System. out. print1n("=====方法执行后=====");
        }
        //在环绕增强中,我们可以给定一个参数, 代表我们要获取处理切入的点;:
        @Around("execution(* com. kuang. service . UserServiceImp1. *(..))")
        public void around(ProceedingJoinPoint jp) throws Throwable {
            System.out.print1n("环绕前");
            Signature signature = jp.getSignature();//获得签名
            System.out.println("signature :"+signature);
            object proceed = jp.proceed(); //执行方法
            System.out.print1n("环绕后");
            System.out.println( proceed);
}
<bean id=" annotationPointCut" class=" com. kuang. diy . AnnotationPointCut"/>
<!--开启注解支持! JDK(默认 proxy-target-class= "false")  cglib (proxy-target-class="true") -->
<aop: aspectj-autoproxy  proxy-target-class= "true"/>


代理模式
优点:
●可以使真实角色的操作更加纯粹 不用去关注一些公共的业务
●公共也就就交给代理角色!实现了业务的分工
●公共业务发生扩展的时候,方便集中管理
缺点:
●一个真实角色就会产生一个代理角色;代码量会翻倍 ,开发效率会变低

AOP面向切面编程-----代理模式

1.静态代理
角色分析:
抽象角色:一般会使用接口或者抽象类来解决;
真实角色:被代理的角色;
代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作;
客户:访问代理对象的人。
2.动态代理
动态代理和静态代理角色一样;
动态代理的代理类 是动态生成的,不是我们直接写好的;
动态代理分为两大类:
基于接口:JDK动态代理;
基于类:cglib;
java字节码实现:javasist。


以下是AOP理解小案例

//动态代理的写法
//等我们会用这个类,自动生成代理类!
public class ProxyInvocationHandler implements InvocationHandler {
    //被代理的接口
    private Rent rent;
    public void setRent(Rent rent) {
        this.rent = rent;
        }
    //生成得到代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
    }
    //处理代理实例,并返回结果
    public object invoke(object proxy, Method method, object[] args) throws Throwable {|
    //动态代理的本质,就是使用反射机制实现!
            Object result =method.invoke(rent, args);
            seeHouse(); 
            return result;
            fare();|
    }
    public void seeHouse(){
        System. out . print1n("中介带看房子");
    }
    public void fare(){
        System.out.print1n("收中介费");
    }
}

//主函数调用
public class Client {
public static void main(String[] args) {
        //真实角色
        Host host = new Host( ) ;
        //代理角色:现在没有
        ProxyInvocationHandler pih = new ProxyInvocationHand1er() ;
        //通过调用程序处理角色来处理我们要调用的接口对象!
        pih. setRent(host);
       Rent proxy = (Rent) pih. getProxy();
       proxy .rent();
    }
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值