cglib动态代理

1.示例需要代码

1.接口代码
public interface People {

	public String workAndGetReward();

	public String reward();

}
2.接口实现类代码
public class Programmer implements People {

	@Override
	public String workAndGetReward() {
		System.out.println("Programmer works hard under 996.");
		return reward();
	}

	@Override
	public String reward() {
		return "Then he goes icu.";
	}

}
3.动态代理处理类代码
import java.lang.reflect.Method;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

public class CglibProxy implements MethodInterceptor {
	private static Logger logger = LoggerFactory.getLogger(Programmer.class);

	@Override
	public Object intercept(Object proxy, Method method, Object[] params, MethodProxy methodProxy) throws Throwable {
		logger.info("before invoke:" + method.getName() + " - " + System.currentTimeMillis());
		Object retObj = methodProxy.invokeSuper(proxy, params);
		logger.info("after invoke:" + method.getName() + " - " + System.currentTimeMillis());
		return retObj;
	}

	// 返回目标对象的代理对象
	public Object newProxy(Object target) {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(target.getClass());
		enhancer.setCallback(this);
		enhancer.setClassLoader(target.getClass().getClassLoader());
		return enhancer.create();
	}

}
4.main代码
public class App {

	public static void main(String[] args) {

		// 要代理的真实对象
		Programmer programmer = new Programmer();
		// 生成MethodInterceptor对象
		CglibProxy proxy = new CglibProxy();
		// 根据真实对象生成代理对象
		Programmer proxyProgrammer = (Programmer) proxy.newProxy(programmer);

		System.out.println(proxyProgrammer.workAndGetReward() + " - " + System.currentTimeMillis());

	}
}

2.代码分析

cglib动态代理的核心是
Enhancer对象
我们可以通过以下步骤实现动态代理

  1. 创建Enhancer实例
  2. 通过setSuperclass方法来设置目标类
  3. 通过setCallback 方法来设置拦截对象
  4. create方法生成Target的代理类,并返回代理类的相应代理对象实例

通过这个方法和三个参数我们得到传入类型的代理对象,然后在调用方法时,会经过我们自定义的代理方法增强了,如以下输出:

[main] INFO 反射.cglib动态代理.v1.Programmer - before invoke:workAndGetReward - 1554827985920
[main] INFO 反射.cglib动态代理.v1.Programmer - before invoke:reward - 1554827985929
[main] INFO 反射.cglib动态代理.v1.Programmer - after invoke:reward - 1554827985929
[main] INFO 反射.cglib动态代理.v1.Programmer - after invoke:workAndGetReward - 1554827985929
Programmer works hard under 996.
Then he goes icu. - 1554827985929

从控制台的输出可以看出来workAndGetReward()方法受到了动态代理的增强
在workAndGetReward()里调用的reward()方法也受到增强

3.代码修改一

cglib也可以不用实现接口来进行动态代理
修改后的真实对象类代码:

public class Programmer {

	public String workAndGetReward() {
		System.out.println("Programmer works hard under 996.");
		return reward();
	}

	public String reward() {
		return "Then he goes icu.";
	}

}

输出:

[main] INFO 反射.cglib动态代理.v1.Programmer - before invoke:workAndGetReward - 1554828540025
[main] INFO 反射.cglib动态代理.v1.Programmer - before invoke:reward - 1554828540034
Programmer works hard under 996.
[main] INFO 反射.cglib动态代理.v1.Programmer - after invoke:reward - 1554828540034
[main] INFO 反射.cglib动态代理.v1.Programmer - after invoke:workAndGetReward - 1554828540034
Then he goes icu. - 1554828540034

可以看到输出顺序略有不同,猜测还会产生其他影响

4.代码修改二

如果我们把内部调用的方法改为final(private方法也会被隐形标记为final)
修改后的真实对象类代码:

public class Programmer {

	public String workAndGetReward() {
		System.out.println("Programmer works hard under 996.");
		return reward();
	}

	private String reward() {
		return "Then he goes icu.";
	}

}

输出:

[main] INFO 反射.cglib动态代理.v1.Programmer - before invoke:workAndGetReward - 1554828701583
[main] INFO 反射.cglib动态代理.v1.Programmer - after invoke:workAndGetReward - 1554828701592
Programmer works hard under 996.
Then he goes icu. - 1554828701592

可以看出此时内部调用的reward()方法不会被代理类增强了

cglib是通过生成被代理类的子类覆写被代理类里的所有非final的方法实现方法增强,与方法是内部调用还是外部调用无关,只与方法有没有被final修饰有关(private方法会被隐形修饰为final)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值