静态代理与动态代理
代理,指的就是将原本真实角色要做的事情交给别人去做,同时在前或后做一些别的事情,比如日志
静态代理与动态代理最大的区别,就是静态代理类一个是事先写好的,程序员已经编写好了对应真实角色的代理,等着去调用就行了。
这种静态代理最大的弊端就是会成倍的增加代码量,比如输出一句正在调用什么方法,你需要每个方法里都写一句输出,为了解决这个困难,可以使用动态代理。
动态代理,就是将代理类的生成自动化,使用反射的机制生成代理类,我们用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与动态代理的关系:
- 两者都不需要手动创建代理类
- 两者都是通过反射获取方法及对应类的名字
- 都是通过多态上转型为对应接口
总的来说,AOP其实是实现了动态代理的一种方式,这种方式的核心思想就是动态的创建代理,通过反射得到方法及类的信息,并进行一些操作
Comments | NOTHING