一、Srping框架的AOP技术底层也是采用的代理技术,代理的方式提供了两种
一、Srping框架的AOP技术底层也是采用的代理技术,代理的方式提供了两种
1. 基于JDK的动态代理
必须是面向接口的,只有实现了具体接口的类才能生成代理对象
2. 基于CGLIB动态代理
对于没有实现了接口的类,也可以产生代理,产生这个类的子类的方式
2. Spring的传统AOP中根据类是否实现接口,来采用不同的代理方式
1. 如果实现类接口,使用JDK动态代理完成AOP
2. 如果没有实现接口,采用CGLIB动态代理完成AOP
二、代理模式
Proxy Pattern(即:代理模式),23种常用的面向对象软件的设计模式之一
代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
优点:
(1).职责清晰
真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。
(2).代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了的作用和保护了目标对象的作用。
(3).高扩展性
结构
一个是真正的你要访问的对象(目标类),另一个是代理对象,真正对象与代理
对象实现同一个接口,先访问代理类再访问真正要访问的对象。
代理模式简单案例
1、jdk动态代理
Java.lang.reflect.Proxy类可以直接生成一个代理对象
Proxy.newProxyInstance():产生代理类的实例。仅能代理实现至少一个接口的类
ClassLoader:类加载器。固定写法,和被代理类使用相同的类加载器即可。
Class[] interface:代理类要实现的接口。固定写法,和被代理类使用相同的接口即可。
InvocationHandler:策略(方案)设计模式的应用。如何代理?
InvocationHandler中的invoke方法:调用代理类的任何方法,此方法都会执行
Object proxy:代理对象本身的引用。一般用不着。
Method method:当前调用的方法。
Object[] args:当前方法用到的参数
目标类接口:
public interface WorkInter {
void workInDay(double money);
void workInNight(double money);
}
目标类:
public class Worker implements WorkInter{
@Override
public void workInDay(double money) {
System.out.println("workInDay");
}
@Override
public void workInNight(double money) {
System.out.println("workInNight");
}
}
代理类:
public class JdkProxy {
@Test
public void run() {
WorkInter proxy = (WorkInter) Proxy.newProxyInstance(Worker.class.getClassLoader(), Worker.class.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("中介费"+((double)args[0])/2);
Object invoke = method.invoke(Worker.class.newInstance(), args);
System.out.println("下班");
return invoke;
}
});
proxy.workInDay(500);
proxy.workInNight(1000);
}
}
执行结果:
2、CGLIB字节码增强
核心类:Enhancer
- 没有接口,只有实现类。
- 采用字节码增强框架 cglib,在运行时 创建目标类的子类,从而对目标类进行增强。
实现步骤:
- 获得代理类的核心类Enhancer对象
- 设置父类(目标类),setSuperclass()方法,底层是创建目标类的子类
- 设置回调函数enhancer.setCallback(new MethodInterceptor())
- 创建代理对象 create()方法
目标类:
public class Worker{
public void workInDay(double money) {
System.out.println("workInDay");
}
public void workInNight(double money) {
System.out.println("workInNight");
}
}
代理类:
public class WorkerProxy {
@Test
public void run() {
Enhancer enhancer=new Enhancer();
//2.设置父类(目标类),setSuperclass()方法,底层是创建目标类的子类
enhancer.setSuperclass(Worker.class);
//3.设置回调函数enhancer.setCallback(new MethodInterceptor())
enhancer.setCallback(new MethodInterceptor() {
*//**
* Object object:代理对象
* Method method:目标类的方法
* Object[] args:方法的形参
* MethodProxy methodProxy:方法的代理对象
*
*//*
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
// TODO Auto-generated method stub
//开启事务
//前置通知
System.out.println("代理收取费用"+ (double)args[0]/2);
//执行目标方法,需要目标类实例
Object invoke = method.invoke(Worker.class.newInstance(), (double)args[0]/2);
//后置通知
System.out.println("go home~~~~~");
return invoke;
}
});
//4.创建代理对象 create()方法
Worker workerPeoxy = (Worker) enhancer.create();
workerPeoxy.workInDay(500);
workerPeoxy.workInNight(1000);
}
}