Spring入门(八)静态代理与动态代理(jdk、cglib)

前言

      本章讲解静态代理和动态代理

方法

一、静态代理

在前面的章节中,我已经介绍了静态代理设计模式,接下来我们继续研究。

优点:

  • 保护真实对象
  • 让真实对象指责更加明确
  • 扩展功能

举例:有一个老板(Boos)和一个秘书(Secretary),老板拥有开会、吃饭、游玩等功能。我们直接就可以产生老板对象并调用相应方法进行实现。但是,例如开会还要有会前的布置工作、会后的具体任务,其不是老板的功能,这个时候我们需要对老板的功能做扩展。使用秘书类代理老板处理其他业务,让老板专心注意于自己的业务即可。

1)新建Boos.java、Secretary.java、功能接口Features.java内容如下

package cn.edu.ccut;

public class Boos implements Features{
	private String name;
	
	public Boos() {}
	
	public Boos(String name) {
		this.name = name;
	}
	
	@Override
	public void meeting() {
		System.out.println("领导开会");
	}

	@Override
	public void eat() {
		System.out.println("领导吃饭");
	}

	@Override
	public void play() {
		System.out.println("领导游玩");
	}

}
package cn.edu.ccut;

public class Secretary implements Features{
	
	private Boos boos = new Boos("李总");
	
	@Override
	public void meeting() {
		System.out.println("开会前准备");
		this.boos.meeting();
		System.out.println("散会");
	}

	@Override
	public void eat() {
		System.out.println("吃饭前准备");
		this.boos.eat();
		System.out.println("送客");
	}

	@Override
	public void play() {
		System.out.println("游玩前准备");
		this.boos.play();
		System.out.println("回城");
	}

}
package cn.edu.ccut;

public interface Features {
	
	public void meeting();
	
	public void eat();
	
	public void play();
}

2)新建测试类Test.java进行测试

package cn.edu.ccut;

public class Test {
	
	public static void main(String[] args) {
		//新建秘书对象
		Secretary secretary = new Secretary();
		//开会
		secretary.meeting();
	}
}

测试结果如下:

完美的实现了静态代理。但是也有一些缺点:

  •  当真实对象的功能很多时,代理类也必须编写同样的方法,比较麻烦

接下来的动态代理解决了这一问题,代理类可以写一个方法即可!

二、动态代理(JDK)

为了优化静态代理带来的缺点,动态代理应运而生,其中就包括我们的JDK动态代理!

既然是JDK动态代理,那么也就拥有JDK就足够了。

本次依然拿老板和秘书为例作为讲解。

优点:JDK自带,无需引入外部的jar

缺点:真实对象必须实现接口;利用反射机制,效率不高

1)编写代理类如下

package cn.edu.ccut;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class Secretary implements InvocationHandler{
	
	private Boos boos = new Boos("李总");

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("准备工作");
		Object obj = method.invoke(this.boos, args);
		System.out.println("结束工作");
		return obj;
	}

}

2)编写测试类进行测试

package cn.edu.ccut;

import java.lang.reflect.Proxy;

public class Test {
	
	public static void main(String[] args) {
		Features boosProxy = (Features) Proxy.newProxyInstance(Test.class.getClassLoader(), new Class[] {Features.class}, new Secretary());
		boosProxy.meeting();
	}
}

测试结果如下:

 完美的实现了JDK动态代理。

三、动态代理(CGLIB)

为了优化JDK动态代理带来的缺点,CGLIB动态代理应运而生!

cglib基于字节码机制,可生成真实对象的子类而非JDK代理生成的代理对象

优点:真实对象无需实现接口;效率高

缺点:需引入外部的jar

1)准备工作

需要引入cglib的相关jar包

 

2)编写代理类如下

package cn.edu.ccut;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class Secretary implements MethodInterceptor{
	
	@Override
	public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
		System.out.println("准备工作");
		Object obj = arg3.invokeSuper(arg0, arg2);
		System.out.println("结束工作");
		return obj;
	}
	
}

3)编写测试类

package cn.edu.ccut;

import net.sf.cglib.proxy.Enhancer;

public class Test {
	
	public static void main(String[] args) {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(Boos.class);
		enhancer.setCallback(new Secretary());
		Boos boos = (Boos) enhancer.create();
		boos.meeting();
	}
}

测试结果如下:

 完美的实现了CGLIB动态代理。

 

总结:

       当我们使用SpringAOP的时候,其底层原理就是动态代理机制!

Spring默认采用JDK动态代理,我们需要在Spring配置文件加入如下配置强制其使用CGLIB动态代理,以便于操作:

<!-- 
    true表示Cglib动态代理
    false表示JDK动态代理
 -->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值