理解AOP概念,学会AOP的使用

理解AOP概念,学会AOP的使用

AOP思想

AOP(Aspect Orient Programming),面向切面编程,作为面向对象(OOP)的一种补充,用于处理系统中分布于各个模块的横切关注点,比如事务管理、日志、异常处理等。为了将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,Spring 提供了面向切面的编程方式,形成一个独立的切面,AOP可以将这部分独立的代码动态的切入到指定方法、指定位置中。

AOP原理

​ AOP可以在编译时候将代码织入到指定的方法或者属性上,或者在运行的时候动态的将代码切入到指定的方法或者属性中,AOP实现的关键就是创建AOP代理,代理有静态代理和动态代理之分,其中aspectj为静态代理在编译器植入,Spring AOP是动态代理在运行期植入。

AOP概念

  • Aspect (切面): 一个关注点的模块化,这个关注点可能会横切多个对象,切面由切入点和通知组成。
  • Adivice(通知/增强): 想要在目标方法出增加的功能或操作,包括前置、后置、环绕等通知类型,很多时候就是所说的拦截器。
  • Pointcut(切入点):目标对象中已经增强的方法,就是说在连接点的基础上选中想要的方法,使用通知。
  • JointPoint (连接点):在目标对象中所有可以增强的方法,Spring中允许你通知的地方,Spring只支持方法连接点,和方法有关的前前后后都是连接点。
  • Target(目标):被一个或者多个切面增强的对象,也就是被通知的对象,应为Spring AOP是通过动态代理实现的,所以这个对象也是被代理的对象。
  • Proxy(代理):将通知织入到目标对象之后,形成了代理对象。
  • Weaving(织入):将切面连接到切点,并形成一个代理对象的过程。

代理实例

静态代理模式
public class StaticProxy implements IUserDao {

    private IUserDao iUserDao;
    public StaticProxy(IUserDao iUserDao){
        this.iUserDao = iUserDao;
    }
    @Override
    public void save() {
        System.out.println("---------------开启事务-------------------");
        iUserDao.save();
        System.out.println("------------------提交事务--------------------");
    }

    public static void main(String[] args) {
        //目标对象
        IUserDao target = new UserDao();
        //静态代理
        StaticProxy proxy = new StaticProxy(target);
        proxy.save();
    }
}


interface IUserDao{
    public void save();
}

class UserDao implements IUserDao {
    @Override
    public void save() {
        System.out.println("----------------保存数据-----------------");
    }
}
关于静态代理的优缺点:
  • 优点:可以在不修改目标对象的前提下扩展目标对象的功能。

  • 缺点:

    ​ 冗余。由于代理对象要实现与目标对象一致的接口,会产生过多的代理类。

    ​ 不易维护。一旦接口增加方法,目标对象与代理对象都要进行修改。

动态代理模式
public class DynamicProxy {
    //维护一个目标对象
    private Object target;

    public DynamicProxy(Object target){
        this.target = target;
    }

    // 为目标对象生成代理对象 
    public Object getProxyInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
                new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("开启事务");

                        // 执行目标对象方法
                        Object returnValue = method.invoke(target, args);

                        System.out.println("提交事务");
                        return returnValue;
                    }
                });
    }

    public static void main(String[] args) {
        IUserDao2 userDao2 = new UserDao2();
        System.out.println(userDao2.getClass());
        IUserDao2 proxy = (IUserDao2) new DynamicProxy(userDao2).getProxyInstance();
        System.out.println(proxy.getClass());
        proxy.save();
    }
}


interface IUserDao2{
    void save();
}
class UserDao2 implements IUserDao2{
    @Override
    public void save() {
        System.out.println("-----------数据保存-----------------");
    }
}

动态代理的特点:

动态代理对象不需要实现接口,但是要求目标对象必须实现接口,否则不能使用动态代理。

动态代理和静态代理的区别
  • 静态代理在编译时就已经实现,编译完成后代理类是一个实际的class文件
  • 动态代理是在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到JVM中
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值