动态代理学习

动态代理

特点:

字节码随用随创建,随用随加载。

作用:

不修改源码的基础上对方法增强。

分类

基于接口的动态代理
提供者:JDK 官方的 Proxy 类。
要求:被代理类最少实现一个接口。
利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

基于子类的动态代理
提供者:第三方的 CGLib,如果报 asmxxxx 异常,需要导入 asm.jar。
要求:被代理类不能用 final 修饰的类(最终类)。
利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。

基于接口的动态代理

模拟人的行为

Person

public interface Person {

    //日常行为
    void dailyBehavior();
}

Student

public class Student implements Person {
    private String msg = "学生党";

    public void dailyBehavior() {
        System.out.println("睡觉");
        System.out.println("吃饭");

    }

}

PersonProxy

public class PersonProxy implements InvocationHandler {
    private Person person;
    public PersonProxy(Person person){
        this.person = person;
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        method.invoke(person,args);
        if(person instanceof Student){
            System.out.println("去学校上课");
        }
        if(person instanceof Student){
            System.out.println("放学回家");
        }
        return null;
    }
}

test

public class test {
    public static void main(String[] args) {
        Student student = new Student();
        PersonProxy personProxy = new PersonProxy(student);
        Person o = (Person)Proxy.newProxyInstance(test.class.getClassLoader(),student.getClass().getInterfaces(), personProxy);

        o.dailyBehavior();
    }
}

结果

睡觉
吃饭
去学校上课
放学回家

基于子类的动态代理

父类

public class SayHello {
 public void say(){
  System.out.println("hello everyone");
 }
}

代理类

public class CglibProxy implements MethodInterceptor{
 private Enhancer enhancer = new Enhancer();
 public Object getProxy(Class clazz){
  //设置需要创建子类的类
  enhancer.setSuperclass(clazz);
  enhancer.setCallback(this);
  //通过字节码技术动态创建子类实例
  return enhancer.create();
 }
 //实现MethodInterceptor接口方法
 public Object intercept(Object obj, Method method, Object[] args,
   MethodProxy proxy) throws Throwable {
  System.out.println("前置代理");
  //通过代理类调用父类中的方法
  Object result = proxy.invokeSuper(obj, args);
  System.out.println("后置代理");
  return result;
 }
}

/*该类实现了创建子类的方法与代理的方法。
getProxy(SuperClass.class)方法通过入参即父类的字节码通过扩展父类的class来创建代理对象。
intercept()方法拦截所有目标类方法的调用,
obj表示目标类的实例,
method为目标类方法的反射对象,
args为方法的动态入参,
proxy为代理类实例。
proxy.invokeSuper(obj, args)通过代理类调用父类中的方法
*/

test

public class DoCGLib {
 public static void main(String[] args) {
  CglibProxy proxy = new CglibProxy();
  //通过生成子类的方式创建代理类
  SayHello proxyImp = (SayHello)proxy.getProxy(SayHello.class);
  proxyImp.say();
 }
}

结果

前置代理
hello everyone
后置代理

内部类形式

public static void main(String[] args) {
	
	SayHello sayHello =  (SayHello)Enhancer.create(SayHello.class,
	new MethodInterceptor() {
	
		@Override
		public Object intercept(Object proxy, Method method, Object[] args, 
		MethodProxy methodProxy) throws Throwable {
				 System.out.println("前置代理");
  				//通过代理类调用父类中的方法
                  Object result = proxy.invokeSuper(obj, args);
                  System.out.println("后置代理");
                  return result;
				

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值