1.静态代理:
为每个代理类生成一个代理对象
public interface IPerson {
public void findLove();
}
public class Zhangsan implements IPerson {
public void findLove() {
System.out.println("儿子要求肤白貌美大长腿:{}");
}
}
生成一个代理类,代理张三找对象
public class Zhanglaosan implements IPerson {
private Zhangsan zhangsan;
public Zhanglaosan(Zhangsan zhangsan) {
this.zhangsan = zhangsan;
}
public void findLove() {
System.out.println("老张开始物色。。。");
zhangsan.findLove();
System.out.println("开始交往。。。");
}
}
测试一下:
public class Test {
public static void main(String[] args) {
Zhanglaosan zhanglaosan = new Zhanglaosan(new Zhangsan());
zhanglaosan.findLove();
}
}
每个代理类都要生成一个代理对象,十分麻烦,如果赵六要找对象,还得在写一个代理类
2.动态代理
动态代理分jdk的动态代理和cglib的动态代理,相对于静态代理,动态代理不需要为每个代理类生成单独的代理类
2.1 jdk动态代理
public interface IPerson {
public void findLove();
public void buyIure();
}
public class Zhangsan implements IPerson {
public void findLove() {
System.out.println("张三要求肤白貌美大长腿:{}");
}
public void buyIure() {
System.out.println("10万");
}
}
public class ZhaoLiu implements IPerson {
public void findLove() {
System.out.println("赵六要求有车有房,学历高。。。。");
}
public void buyIure() {
System.out.println("99万");
}
}
写在这里插入代码片
一个代理类,可以动态生成代理对象
public class JdkMeipo implements InvocationHandler {
private IPerson target;
public IPerson getInstance(IPerson target) {
this.target = target;
Class<?> clazz = target.getClass();
return (IPerson) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(target, args);
after();
return result;
}
private void before() {
System.out.println("我是媒婆,正在开始物色。。");
}
private void after() {
System.out.println("双方开始交往");
}
}
测试一下:
public class Test {
public static void main(String[] args) {
JdkMeipo meipo = new JdkMeipo();
IPerson zhangsan = meipo.getInstance(new Zhangsan());
zhangsan.findLove();
System.out.println("分割线---------------------");
IPerson zhaoliu = meipo.getInstance(new ZhaoLiu());
zhaoliu.findLove();
zhaoliu.buyIure();
}
}
2.2 cglib动态代理
public class Zhangsan {
public final void findLove() {
System.out.println("张三要求肤白貌美大长腿:{}");
}
}
public class CglibMeipo implements MethodInterceptor {
private Object target;
public Object getInstace(Object target){
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
Object o = enhancer.create();
return o;
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
Object invoke = method.invoke(target, objects);
after();
return invoke;
}
private void before() {
System.out.println("我是媒婆,正在开始物色。。");
}
private void after() {
System.out.println("双方开始交往");
}
}
测试一下:
public class TestCglib {
public static void main(String[] args) {
CglibMeipo cg = new CglibMeipo();
Zhangsan zhangsan = (Zhangsan)cg.getInstace(new Zhangsan());
zhangsan.findLove();
}
}
优缺点:
1.都是采用生成字节码,重组成一个新的类
2:实现方式不同 Cglib是采用继承的方式,覆盖目标代理类的方法,目标代理类中用final 修饰的方法不会被扩展增强;
Jdk采用实现接口的方式,要求代理目标类必须实现一个接口
3.Jdk的实现方式调用更复杂,cglib更简单
4.效率上jdk的动态代理效率低,每次调用都会使用反射原理,比较耗时,cglib这种方式效率更高,没有用到反射
代理模式将代理对象与真实被调用的对象分离,一定程度上降低了系统的耦合度,易于扩展,在一定程度上起到了保护目标对象的作用,增强目标对象的职责。
3.Spring中如何选择代理模式的?
1.如果bean 有实现类,则采用jdk的动态代理,没有的话采用cglib的方式。
2.Spring中可以通过配置,强制使用cglib的代理方式 <aop:aspectj-autoproxy proxy-target-class=“true”/>