静态代理与动态代理

代理,指的就是将原本真实角色要做的事情交给别人去做,同时在前或后做一些别的事情,比如日志

静态代理与动态代理最大的区别,就是静态代理类一个是事先写好的,程序员已经编写好了对应真实角色的代理,等着去调用就行了。

这种静态代理最大的弊端就是会成倍的增加代码量,比如输出一句正在调用什么方法,你需要每个方法里都写一句输出,为了解决这个困难,可以使用动态代理。

动态代理,就是将代理类的生成自动化,使用反射的机制生成代理类,我们用JDK的动态代理来举个例子:

InvocationHandler在这个接口中,我们使用newProxyInstance方法来生成代理类,其中我们只需要提供对应的类加载器,真实角色所实现的接口,还有生成代理类方法的类本身这三个参数,就可以直接创建一个代理类,我们通过这个代理类来执行真是角色的一些方法,这时会调用反射机制也就是invoke方法,我们可以在invoke方法里写上一些附加的供能

动态代理与AOP

为什么我们说aop也实现了动态代理呢?

仔细看Spring的AOP实现。

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void query();
}
public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("增加了一个用户");
    }

    @Override
    public void delete() {
        System.out.println("删除了一个用户");
    }

    @Override
    public void update() {
        System.out.println("修改了一个用户");
    }

    @Override
    public void query() {
        System.out.println("查询了一个用户");
    }
}

首先写好服务接口,然后写一个impl实现类,这个实现类对应我们的真实角色。

在spring中,找到切点,并且对着特定的切点下特定的通知(方法),这个过程很像JDK动态代理的Invoke

<aop:config>
    <!--切入点:需要在哪里执行我们的方法expression:表达式,execution(要执行的位置)-->
    <aop:pointcut id="pointcut" expression="execution(* com.zhaox.service.UserServiceImpl.*(..))"/>
    <!--执行环绕增加-->
    <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
    <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>

</aop:config>

接下来在测试类中,我么就要去找到我们的代理了,那么谁是我们的代理呢?在JDK动态代理中,我们有单独的方法来创建代理,具体的方式也是通过多态,得到一个类型为接口类型的代理

 Rent proxy = (Rent) proxyInvocationHandler.getProxy();

但是在Spring中,我们是无需建立对象的,需要的对象都变成了bean,我们只需要获得UserServiceImpl的bean,并转为接口类型

UserService bean = context.getBean("userService",UserService.class);

总结:

SpringAOP与动态代理的关系:

  1. 两者都不需要手动创建代理类
  2. 两者都是通过反射获取方法及对应类的名字
  3. 都是通过多态上转型为对应接口

总的来说,AOP其实是实现了动态代理的一种方式,这种方式的核心思想就是动态的创建代理,通过反射得到方法及类的信息,并进行一些操作


醉后不知天在水,满船清梦压星河