<尚学堂>
八. 代理设计模式
- 设计模式:前人总结的一套解决特定问题的代码.
- 代理设计模式优点:
2.1 保护真实对象
2.2 让真实对象职责更明确
2.3 扩展 - 代理设计模式
3.1 真实对象(老总)
3.2 代理对象(秘书)
3.3 抽象对象(抽象功能),谈小目标
九. 静态代理设计模式
- 由代理对象代理所有真实对象的功能.
1.1 自己编写代理类
1.2 每个代理的功能需要单独编写 - 静态代理设计模式的缺点:
2.1 当代理功能比较多时,代理类中方法需要写很多.
//抽象对象(抽象功能)
package com.bjsxt;
public interface Gongneng {
void chifan();
void mubiao();
}
//代理对象(秘书)
package com.bjsxt;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class Mishu implements InvocationHandler {
private Laozong laozong=new Laozong() ;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("预约时间");
Object result = method.invoke(laozong, args);
System.out.println("记录访客信息");
return result;
}
}
//真实对象(老总)
package com.bjsxt;
public class Laozong implements Gongneng{
@Override
public void chifan() {
System.out.println("吃饭");
}
@Override
public void mubiao() {
System.out.println("目标");
}
}
十. 动态代理
- 为了解决静态代理频繁编写代理功能缺点.
- 分类:
2.1 JDK 提供的
2.2 cglib 动态代理
十一. JDK 动态代理
- 和 cglib 动态代理对比
1.1 优点:jdk 自带,不需要额外导入 jar
1.2 缺点:
1.2.1 真实对象必须实现接口
1.2.2 利用反射机制.效率不高. - 使用 JDK 动态代理时可能出现下面异常
2.1 出现原因:希望把接口对象转换为具体真实对象
package com.bjsxt;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class Mishu implements InvocationHandler {
private Laozong laozong=new Laozong() ;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("预约时间");
Object result = method.invoke(laozong, args);
System.out.println("记录访客信息");
return result;
}
}
package com.bjsxt;
import java.lang.reflect.Proxy;
public class Women {
public static void main(String[] args) {
System.out.println(Women.class.getClassLoader()==Laozong.class.getClassLoader());
Mishu mishu = new Mishu();
//第一个参数:反射时使用的类加载器
//第二个参数:Proxy需要实现什么接口
//第三个参数:通过接口对象调用方法时,需要调用哪个类的invoke方法
Gongneng gongneng = (Gongneng) Proxy.newProxyInstance(Women.class.getClassLoader(), new Class[]{Gongneng.class}, mishu);
Laozong laozong = (Laozong) gongneng;
// gongneng.chifan();
}
}
十二: cglib 动态代理
- cglib 优点:
1.1 基于字节码,生成真实对象的子类.
1.1.1 运行效率高于 JDK 动态代理.
1.2 不需要实现接口 - cglib 缺点:
2.1 非 JDK 功能,需要额外导入 jar
package com.bjsxt;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class Mishu implements MethodInterceptor{
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
System.out.println("预约时间");
//invoke()调用子类重写的方法
// arg1.invoke(arg0, arg2);
// arg3.invokeSuper(arg0, arg2);
Object result = arg3.invokeSuper(arg0, arg2);
System.out.println("备注");
return result;
}
}
package com.bjsxt;
import net.sf.cglib.proxy.Enhancer;
public class Women {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Laozong.class);
enhancer.setCallback(new Mishu());
Laozong laozong = (Laozong) enhancer.create();
laozong.chifan();
}
}
- 使用 spring aop 时,只要出现 Proxy 和真实对象转换异常
3.1 设置为 true 使用 cglib
3.2 设置为 false 使用 jdk(默认值)
<aop:aspectj-autoproxy
proxy-target-class="true"></aop:aspectj-autoproxy>