作为学习Spring的一个基础,代理模式是了解的一个点。
代理模式:通过代理对象访问目标对象,并且可以对在不修改目标对象的情况下,在代理对象中增加额外的功能。
静态代理:通常只代理一个类(单一目标对象),使用前就已经知道被代理对象是什么,并且代理对象必须实现被代理对象相同的接口。(静态:类型是先预定好的,不可改变)
动态代理:代理类不需要实现接口,只有在运行时才知道代理的是什么对象。
JDK动态代理(目标对象实现了接口):实现InvocationHandler的invoke方法,通过Proxy.newProxyInstance得到代理对象。
CGLIB动态代理:可代理接口和类,不需要业务类继承接口,通过在内存中构建一个子类来进行代理。页脚子类代理。
静态代理:
/** 商品模块接口 */
interface IGoods{
/* 购买商品 */
void buyGoods();
}
/** 购买商品的实现 */
class GoodsImpl implements IGoods{
@Override
public void buyGoods() {
System.out.println("购买了一个商品");
}
}
/** 代理类 */
class GoodsProxy implements IGoods{
private IGoods iGoods;
//构造方法传入代理对象
public GoodsProxy(IGoods iGoods){
this.iGoods = iGoods;
}
@Override
public void buyGoods() {
System.out.println("选择了一个面包之后");
this.iGoods.buyGoods();
System.out.println("打包走人");
}
}
public class AppStaticProxy {
public static void main(String[] args) {
IGoods iGoods = new GoodsImpl();
GoodsProxy goodsProxy = new GoodsProxy(iGoods);
goodsProxy.buyGoods();
}
}
缺点:代理对象需要和目标对象实现一样的接口,如果目标太多,就会产生很多代理类。一旦接口增加,代理对象和目标对象都需要修改。使用动态代理方式,可以避免这类问题。
动态代理(JDK)
如果被代理对象实现了接口
package MyCode;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/** 商品业务接口 */
interface IGoods2{
void buyGoods();
}
/** A购买商品的实现 */
class AGoodsImpl implements IGoods2{
@Override
public void buyGoods() {
System.out.println("付钱购买");
}
}
/** B购买商品的实现 */
class BGoodsImpl implements IGoods2{
@Override
public void buyGoods() {
System.out.println("刷卡购买");
}
}
/** 代理工厂 */
class ProxyFactory{
Object target;
public ProxyFactory(Object target){
this.target = target;
}
/* 获取代理对象 */
public Object getProxyInstance(){
//实现 invoke 方法
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("选择商品种类");
Object retVal = method.invoke(target,args);
System.out.println("打包走人");
return retVal;
}
};
//返回代理对象
Object object = Proxy.newProxyInstance(this.target.getClass().getClassLoader(), //目标类的ClassLoader
this.target.getClass().getInterfaces(), //目标类的Interfaces
invocationHandler);
return object;
}
}
public class AppJDKProxy {
public static void main(String[] args) {
IGoods2 AGoods = new AGoodsImpl(); //付钱
IGoods2 BGoods = new BGoodsImpl(); //刷卡
//通过代理获取两个目标对象
IGoods2 proxyGoods = (IGoods2) new ProxyFactory(AGoods).getProxyInstance();
proxyGoods.buyGoods();
proxyGoods = (IGoods2) new ProxyFactory(BGoods).getProxyInstance();
proxyGoods.buyGoods();
}
}
动态代理(CGLIB)
代码以代理类的情况进行演示,第一步引入Cglib包
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
package MyCode;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/** A 商品购买 */
class AGoods{
public void buyGoods() {
System.out.println("付钱购买");
}
}
/** B 商品购买实现 */
class BGoods{
public void buyGoods() {
System.out.println("刷卡购买");
}
}
/** 代理工厂 实现MethodInterceptor*/
class CGProxyFactory implements MethodInterceptor {
Object target;
public CGProxyFactory(Object target){
this.target = target;
}
//提供获取代理对象的方法
public Object getProxyInstance(){
Enhancer enhancer = new Enhancer(); //工具类
enhancer.setSuperclass(this.target.getClass()); //设置父类(目标对象)
enhancer.setCallback(this); //设置回调函数
return enhancer.create(); //创建子类对象
}
//重写intercept方法
@Override
public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("选择商品种类");
Object retObj = method.invoke(this.target,objects);
System.out.println("付钱购买");
return retObj;
}
}
public class AppCglib {
public static void main(String[] args) {
AGoods aGoods = new AGoods();
BGoods bGoods = new BGoods();
AGoods proxyAGoods = (AGoods)new CGProxyFactory(aGoods).getProxyInstance();
proxyAGoods.buyGoods();
BGoods proxyBGoods = (BGoods)new CGProxyFactory(bGoods).getProxyInstance();
proxyBGoods.buyGoods();
}
}
网友评论