Spring的AOP

本文深入探讨了Spring的AOP(面向切面编程)概念,包括其减少代码重复性、增强代码可维护性的优势。AOP主要用于日志、事务管理、权限控制和缓存优化等场景。文章介绍了AOP的基本原理,强调了代理在运行时动态切入代码的能力,以及静态代理和动态代理的区别。动态代理分为JDK动态代理和CGLIB动态代理,SpringAOP是其典型应用。此外,文章还详细阐述了AOP的相关术语,如连接点、切入点、增强和切面,以及如何通过AspectJ进行注解配置。
摘要由CSDN通过智能技术生成

AOP综述:
作者:欲眼熊猫
链接:https://www.zhihu.com/question/24863332/answer/48376158
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

:这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。

面向切面编程(AOP是Aspect Oriented Program的首字母缩写) ,我们知道,面向对象的特点是继承、多态和封装。而封装就要求将功能分散到不同的对象中去,这在软件设计中往往称为职责分配**。实际上也就是说,让不同的类设计不同的方法。这样代码就分散到一个个的类中去了。这样做的好处是降低了代码的复杂程度,使类可重用**。 但是人们也发现,在分散代码的同时,也增加了代码的重复性。什么意思呢?比如说,我们在两个类中,可能都需要在每个方法中做日志。按面向对象的设计方法,我们就必须在两个类的方法中都加入日志的内容。也许他们是完全相同的,但就是因为面向对象的设计让类与类之间无法联系,而不能将这些重复的代码统一起来。 也许有人会说,那好办啊,我们可以将这段代码写在一个独立的类独立的方法里,然后再在这两个类中调用。但是,这样一来,这两个类跟我们上面提到的独立的类就有耦合了,它的改变会影响这两个类。那么,有没有什么办法,能让我们在需要的时候,随意地加入代码呢?这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。 一般而言,我们管切入到指定类指定方法的代码片段称为切面,而切入到哪些类、哪些方法则叫切入点。有了AOP,我们就可以把几个类共有的代码,抽取到一个切片中,等到需要时再切入对象中去,从而改变其原有的行为。这样看来,AOP其实只是OOP的补充而已。OOP从横向上区分出一个个的类来,而AOP则从纵向上向对象中加入特定的代码。有了AOP,OOP变得立体了。如果加上时间维度,AOP使OOP由原来的二维变为三维了,由平面变成立体了。从技术上来说,AOP基本上是通过代理机制实现的

**这样的做法,对原有代码毫无入侵性,这就是AOP的好处了,把和主业务无关的事情,放到代码外面去做。**在不修改主要业务情况下,插入或者增强一些功能。

AOP场景;
1.日志
2.事务管理
3.权限控制
4.缓存优化

AOP的基本底层原理:
为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别。通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性。

更通俗的说,代理解决的问题当两个类需要通信时,引入第三方代理类,将两个类的关系解耦,让我们只了解代理类即可,而且代理的出现还可以让我们完成与另一个类之间的关系的统一管理,但是切记,代理类和委托类要实现相同的接口,因为代理真正调用的还是委托类的方法。

使用场合举例:

如果需要委托类处理某一业务,那么我们就可以先在代理类中统一处理然后在调用具体实现类

按照代理的创建时期,代理类可以分为两种:

静态:由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。

动态:在程序运行时运用反射机制动态创建而成。也就是自动生成代理类,而不是手动创建代理类。

下面分别用静态代理与动态代理演示一个示例:

添加打印日志的功能,即每个方法调用之前和调用之后写入日志

总结一下:
1.动态代理代理的是行为,也就是接口,动态代理只去代理这个行为,就像专门的房地产代理,只代理房地产这个行为,比如金融代理,只代理金融这个行为,而不是为了某一个人去服务。
2.静态代理,更多是代理某个人,有点像为私人服务的管家。
代理模式
静态代理:
在这里插入图片描述
在这里插入图片描述
这里面,client是租房子的人,Rent是出租房子这个行为,抽象角色一般都是你要做的事情,会是抽象角色。

把简单非必要的事情交给别人做就可以了。
代理模式实现了业务分工,公共业务发生问题时候方便集中管理
在这里插入图片描述
核心关键即使
1.接口
2.真实角色
3.代理角色
4.客户访问
真实角色将所有杂七杂八事情交给代理去做。

静态代理中,代理类和真实类都要实现接口,代理是面向实现类的,一个实现类需要一个代理类,这样冗余代码太多了。
发生业务时候方便进行扩展,业务进行统一管理。
在这里插入图片描述
最大的关键点在这里,接口里放的是行为,我要的是我输入一个东西,你给我一个想要的输出,这些行为放在接口中去。
proxy作为代理,代理需要什么?代理需要有被代理人,还需要明确自己的行为是什么,因此代理里面要有行为**,也就是代理要继承接口重写方法,代理就像个乙方一样,需要明确自己的职责。代理同时还需要心中有甲方,所以被代理的那个真实角色也要在代理中,因为代理需要心中有爸爸。**当然客户爸爸不止一个,根据注入不同你的爸爸也不同。

相当于所有提供的新的需求和功能全部加给代理就行了,而不懂自己本身。甲方爸爸有什么需求,加载代理头上就可了,不会动自己。
在这里插入图片描述
这么一看有点同情代理。
这就是静态代理,一个代理对应一个客户,问题是客户太多,代理也太他妈多了。

AOP的本质就是横着切进去一段业务。
在这里插入图片描述
缺点:

1)代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。

2)代理对象只服务于一种类型的对象,如果要服务多类型的对象。势必要为每一种对象都进行代理,静态代理在程序规模稍大时就无法胜任了。如上的代码是只为UserManager类的访问提供了代理,但是如果还要为其他类如Department类提供代理的话,就需要我们再次添加代理Department的代理类。

动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。而且动态代理的应用使我们的类职责更加单一,复用性更强

package pojo.kuang.demo01;

public interface Rent {
   
    //租房接口
    public abstract void rent();
}

首先是接口,接口中抽象定义了我需要的行为,就像很多sb产品经理一样,只要输出和结果,中间过程完全不管,不管你是不是能实现中间这个过程

然后是真实类,真实类继承接口,执行接口中的行为

package pojo.kuang.demo01;

//房东需要出租房子
public class Host implements Rent {
   
    @Override
    public void rent() {
   
        System.out.println("租房哎");
    }
}

这就是代理商,根据你提供的个人信息,动态给你生成一个代理

package pojo.kuang.demo01;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//动态代理类,自动生成代理类
//实现一个特殊接口
public class ProxyInvactionHandler 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);
        //三个参数,自己类加载器,自己,还有代理的接口类
    }
    //处理代理实例,并且返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   
        Object result = method.invoke(rent, args);
        //这里面放一下,我们需要的接口
        return result;
    }
}

最后是客户访问代理商

package pojo.kuang.demo01;

public class Clinet {
   
    public static void main(String[] args) {
   
        Host host = new Host();
        //这是一个真实角色,就是房东同志
        //我们要生成房东同志的代理

        //那个相当于一个动态代理工厂,而不是某一个人的动态代理,我可以代理很多人哦

        ProxyInvactionHandler pih = new ProxyInvactionHandler();

        pih.setRent(host);
        //host实现了rent接口,是一个接口实现类,所以可以放进去进行代理
        //完成属性注入之后,我们才是一个正常正确色一个代理
        //完成属性注入之后相当于我们已经有,模板注入了,工厂可以进生产了

        Rent proxy = (Rent) pih.getProxy();
        //代理对象被生成了

        proxy.rent();


    }

}

代理类里加东西

package pojo.kuang.demo01;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//动态代理类,自动生成代理类
//实现一个特殊接口
public class ProxyInvactionHandler implements InvocationHandler {
   
    private Rent rent;//被代理的接口,表明自己的职责
//注入一下这个几口
    public void setRent(Rent</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值