代理模式详解

版权声明:本文为博主原创,未经博主允许不得转载。 https://blog.csdn.net/LMD802/article/details/83934005

代理模式

代理模式分为动态代理和静态代理
就是在不修改原代码的基础上,
对原对象进行功能增强

1.静态代理

  • 1.1 要有接口
  • 1.2 遍写接口实现类
  • 1.3 编写代理类,也去实现被代理对象实现的接口
  • 缺点:
    • 1.只能代理一类对象,代理类只能代理实现了被代理对象实现的接口
    • 2.代理对象固定
/**
 * 接口
 * @author 落幕
 */
public interface Work {
	
	void work();
}


/**
 * 接口实现类
 * @author 落幕
 *
 */
public class Programer implements Work {

	@Override
	public void work() {
		// TODO Auto-generated method stub
		System.out.println("Coding...");
	}
}

/**
 * 接口实现类
 * @author 落幕
 */
public class Sell implements Work {

	@Override
	public void work() {
		// TODO Auto-generated method stub
		System.out.println("Selling...");
	}
}

/**
 * 静态代理类
 * @author 落幕
 *
 */
public class StaticProxy implements Work {
	private Object target;
    //提供有参构造
	public StaticProxy(Object target) {
		super();
		this.target = target;
	}

	@Override
	public void work() {
		// TODO Auto-generated method stub
		//其引用要为接口
		Work work = (Work) target;
		work.work();
	}
	
	public static void main(String[] args) {
		//Programer pro = new Programer();
		Sell sell = new Sell();
		StaticProxy factory = new StaticProxy(sell);
		factory.work();
	}
	
}

动态代理

JDK动态代理:java.lang.reflect.Proxy
  • 被代理的对象必须有接口:Class<?>[] interfaces = cls.getInterfaces();因为他需要通过接口创建引用
  • 如果一个类有接口,spring默认使用JDK动态代理创建该类实例
  • 注意
    • 1.JDK动态代理创建的对象只能强转为接口类型,不能强转为实现类类型
    • 2.对象有接口,在SpringDI中只能使用接口类型进行注入
/**
 * 接口
 * @author 落幕
 */
public interface Actor {
	void Act();
}

/**
 * 接口实现类
 * @author 落幕
 */
public class LikeActor implements Actor {

	@Override
	public void Act() {
		// TODO Auto-generated method stub
		System.out.println("喜欢的男演员:胡歌");
	}
}

/**
 * 接口实现类
 * @author 落幕
 */
public class LikeActress implements Actor {

	@Override
	public void Act() {
		// TODO Auto-generated method stub
		System.out.println("喜欢的女演员:林依晨");
	}
}

public class JDKProxy {
	
	private Object target;
	
	public JDKProxy(Object target) {
		super();
		this.target = target;
	}


	public Object createObject() {
		// TODO Auto-generated method stub
		//1.获取类对象
		Class<?> cls = target.getClass();
		//2.获取类加载器
		ClassLoader loader = cls.getClassLoader();
		//3.获取该对象实现的所有接口
		Class<?>[] interfaces = cls.getInterfaces();
		
		return Proxy.newProxyInstance(loader, interfaces, new InvocationHandler() {
			//invoke():代理对象执行方法
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				//通过反射调用方法:
				//Method.invoke(对象名,方法参数列表):Object
				return method.invoke(target, args);
			}
		});
	}
	
	public static void main(String[] args) {
		Programer pro = new Programer();
		JDKProxy proxy = new JDKProxy(pro);
		//要用接口做引用
		Work worker = (Work) proxy.createObject();
		worker.work();
		System.out.println("-------------------");
		LikeActor actor = new LikeActor();
		proxy = new JDKProxy(actor);
		Actor act = (Actor) proxy.createObject();
		act.Act();
		
		
	}
}
cglib动态代理:
  • 被代理的对象无需实现任意接口, 使用spring无需导入cglib.jar
    spring默认整合了cglib
  • 优点:
    可以实现对任意对象的动态代理
/**
 * 接口
 * @author 落幕
 */
public class CglibProxyFactory {
	private Object target;
	public CglibProxyFactory(Object target) {
		super();
		this.target = target;
	}
	
	/**
	 * 创建代理对象
	 * @return
	 */
	public Object createProxyObject(){
		//Enhance:提高,增强
		//1.创建代码增强工具对象
		Enhancer enhancer = new Enhancer();
		//2.指定被代理对象为代理对象的父类
		enhancer.setSuperclass(target.getClass());
		//3.编写代理对象的执行方法
		//MethodInterceptor是Callback的子接口
		enhancer.setCallback(new MethodInterceptor() {
			@Override
			public Object intercept(Object arg0, Method method, Object[] params, MethodProxy arg3) throws Throwable {
				// TODO Auto-generated method stub
				//value:原对象方法执行的返回值
				Object value = method.invoke(target, params);
				return value;
			}
		});
		//4.创建被代理对象
		return enhancer.create();
	}
	public static void main(String[] args) {
		LikeActress actress = new LikeActress();
		CglibFactory proxy = new CglibFactory(actress);
		//可以没有接口
		LikeActress actre = (LikeActress) proxy.createObject();
		actre.act();
	}
}

注意:

类有接口,spring使用JDK动态代理创建对象
类无接口,spring使用cglib动态代理创建对象

猜你喜欢

转载自blog.csdn.net/LMD802/article/details/83934005