Java代理

目录

一、静态代理

原理

特点

二、动态代理(JDK代理)

特点

三、扩展

四、应用


一、静态代理

先看示例

/**
 * 签字类
 * @author HX
 *
 */
public interface Sign {

	/**
	 * 签字接口方法
	 */
	void sign();
}
/**
 * -老板
 * @author HX
 *
 */
public class Boss implements Sign {

	@Override
	public void sign() {
		System.out.println("我是老板,我要签字了!");
	}
}
/**
 * - 这是代理类,秘书
 * @author HX
 *
 */
public class SecretaireProxy implements Sign {

	private Boss boss;
	
	public SecretaireProxy(Boss boss) {
		this.boss = boss;
	}
	
	@Override
	public void sign() {
		System.out.println("老板签字前,秘书先检查");
		boss.sign();
		System.out.println("老板签字后,秘书再作其它处理");
	}
}
/**
 * -一个员工要让老板签字,交到秘书处
 * @author HX
 *
 */
public class Client {

	public static void main(String[] args) {
		// 员工想找老板签字,但其级别不能面老板,只能将签字文件交给老板秘书,
		// 告诉秘书这是需要老板签字的文件(代理 前处理)
		Boss boss = new Boss();
		// 老板秘书将文件进行分类整理,将不需要老板签字的文件处理掉,
		// 将需要老板签字的文件交给老板签字(执行签字方法,告诉老板签字了)
		SecretaireProxy secretaireProxy = new SecretaireProxy(boss);
		// 老板签字完成,秘书取回文件,然后将文件进行分类(按部门或其它),通知文件员工取回文件(代理 后处理)
		secretaireProxy.sign();
	}
}

result:

老板签字前,秘书先检查
我是老板,我要签字了!
老板签字后,秘书再作其它处理

原理

 

Sign接口存在的作用:

让目标对象和代理类实现同一个接口,目的是让客户端访问的时候行为一致

Proxy:代理对象,通常具有以下功能

  1. 实现与具体目标对象一样的接口,这样主要可以使代理类与目标类行为一致。(老板和秘书行为一致)
  2. 保存一个具体的目标对象引用,可以在需要的时候调用具体的目标对象的方法。
  3. 可以控制对具体目标对象的访问

特点

  • 优点:

    可以在不修改目标对象的前提下,对目标对象的功能进行扩展(老板只关注签字,其余处理都交给秘书处理)

  • 缺点:

    1. 代理对象Proxy对象和目标对象寅相同的接口,有一个目标对象就要有一个代理对象,这样会产生许多代理类,臃余太大
    2. 一旦接口增加方法,其实现类(老板和秘书)都要去维护,代价太大


二、动态代理(JDK代理)

基于静态代理的缺点,出现了动态代理

特点:

  1. 不需要自己写代理对象,但是目标对象还是实现接口
  2. 代理对象的生成,是利用JDK API,动态的在内存中构建代理对象
  3. 动态代理也叫JDK代理,接口代理

JDK中生成代理对象的API:

Proxy   java.lang.reflect.Proxy
  static Object newProxyInstance(
      ClassLoader loader,       // 指定当前目标对象使用类加载器
      Class<?>[] interfaces,    // 目标对象实现的接口的类型
      InvocationHandler h       // 事件处理器
  )

示例来了

/**
 * 签字类
 * @author HX
 *
 */
public interface Sign {

	/**
	 * 签字接口方法
	 */
	void sign();
}
/**
 * -老板
 * @author HX
 *
 */
public class Boss implements Sign {

	@Override
	public void sign() {
		System.out.println("我是老板,我要签字了!");
	}
}

代理工厂:这个工厂可以重复使用,只要传入如老板类一样的类

public class ProxyFactory {
	/**
	 * 
	 * @param target 目标对象(就如老板一般的类)
	 * @return 返回代理对象(如秘书类)
	 */
	public static Object getProxyInstance(Object target) {

		return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
				new InvocationHandler() {
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						System.out.println("前处理");
						Object returnValue = method.invoke(target, args);
						System.out.println("后处理");
						return returnValue;
					}
				});
	}
}

员工

/**
 * -一个员工要让老板签字,交到秘书处
 * @author HX
 *
 */
public class Client {
	public static void main(String[] args) {
		// 我要找老板签字
		Sign target = new Boss();
		// 从秘书办公室找个秘书(ProxyFactory)
		Sign proxy = (Sign)ProxyFactory.getProxyInstance(target);
		// 老板
		proxy.sign();
	}
}

result

前处理
我是老板,我要签字了!
后处理

特点

优点:

代理对象不需要实现接口,代理对象也不需要自己创建

缺点:

目标对象一定要实现接口,否则不能用动态代理



三、扩展

CGlib代理:

也叫作子类代理。在内存中构建一个子类对象,从而实现对目标功能的扩展

JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果不想实现接口,就可以使用CGLIB实现。

CGLIB代理要求:⭐目标对象不能为final⭐,否则报错(原理是,CGLIB是通过目标对象的子类创建代理,如果目标对象为final,那就不允许被继承了,就不能使用CGLIB动态代理了)

四、应用

  1. 拦截器
  2. 过滤器
  3. AOP
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值