代理

首先介绍------代理

代理:需要三个对象1:定义规则的接口;2:实现内容的主体;3代理;
其中定义规则的接口中,定义好需要完成的内容;
实现内容的主体要实际完成内容;
最重要的来了:代理中需要注入一个主体,这个主体就是实际完成的对象;代理实现内容,但不是实际执行,只是在方法中去调用主体去完成,这样就可以在完成的前后去添加或者修改内容;
举个例子:A要卖房子,B是中介。客户C去买房子。这里不管是A还是B都可以卖房子,这样就定义接口中的方法卖房子,A实现就是卖自己的房子。重点来了:B实现卖房子,但B没有房子,需要A实际去卖,这样把A登记在B中,B卖房子实际上是A去卖的。。。
C去中介B买的房子还是A的房子,然后被收取中介费,收费过程就是一个对原有过程的增强。代理过程完毕。

然后介绍------静态代理

上代码:

//接口
    public interface Person {
    	public void give();
    }
    //实现类
    public class Student implements Person {
    	public void give() {
    		System.out.println("缴费");
    	}
    }
    //代理类
    public class StuProxy implements Person {
    	Person s;
    	public StuProxy(Person p){
    		this.s=p;
    	}
    	public void give() {
    		System.out.println("班长收费");
    		s.give();
    	}
    }
    //测试
    public static void main(String[] args){
    	//创建实现类
    	Person stu=new Student();
    	//创建代理类
    	Person stuPro=new StuProxy(stu);
    	//代理实现过程
    	stuPro.give();
	}

然后介绍------动态代理之JDK实现

介绍完代理过程了,接下来看静态代理-------就是在编码时就写好了代理的过程。
动态代理就是没有代理类,在程序运行时,去创建代理对象,并且去实现增强。
上代码:

//动态代理类
public class MyInvocationHandler<T> implements InvocationHandler  {
	T t;
	public MyInvocationHandler(T t){
		this.t=t;
	}
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理执行" +method.getName() + "方法");
        //代理过程中插入监测方法,计算该方法耗时
        Object result = method.invoke(t, args);
        return result;
    }
}
  //测试类
   public static void main(String[] args){
   		Person stu=new Student();
    	 //创建一个与代理对象相关联的InvocationHandler
         InvocationHandler stuHandler = new MyInvocationHandler<Person>(stu);
        // 使用Proxy类的getProxyClass静态方法生成一个动态代理类stuProxyClass 
         Class<?> stuProxyClass = Proxy.getProxyClass(Person.class.getClassLoader(), new Class<?>[] {Person.class});
        //获得stuProxyClass 中一个带InvocationHandler参数的构造器constructor
        Constructor<?> constructor = PersonProxy.getConstructor(InvocationHandler.class);
        // 通过构造器constructor来创建一个动态实例stuProxy
        Person stuProxy = (Person) cons.newInstance(stuHandler);
        stuProxy.give();
   }

就此,一个动态代理对象就创建完毕,当然,上面四个步骤可以通过java.lang.reflect.Proxy类的newProxyInstances方法来简化:

 //创建一个与代理对象相关联的InvocationHandler
 InvocationHandler stuHandler = new MyInvocationHandler<Person>(stu);
//创建一个代理对象stuProxy,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
  Person stuProxy= (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler);

查看测试类:

 public static void main(String[] args) {
		//被代理对象
    	Person s=new Student();           	     	
    	InvocationHandler  p=new MyInvocationHandler(s);    
    	//得到代理对象
    	Person stuProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(),new Class<?>[]{Person.class}, p);
    	//代理对象调用代理的方法
    	stuProxy.give();
    }

InvocationHandle实现动态代理局限性:必须要有同意的接口;

然后介绍------动态代理之cglib

import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CGLibProxy implements MethodInterceptor {
	// CGlib需要代理的目标对象 
	private Object targetObject;
	public Object createProxyObject(Object obj) {
		this.targetObject = obj;
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(obj.getClass());
		enhancer.setCallback(this);
		Object proxyObj = enhancer.create();
		return proxyObj;
	}

	public Object intercept(Object proxy, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {
		Object obj = null; 
		// 过滤方法
		if ("addUser".equals(method.getName())) { 
			checkPopedom(); 
			}
		obj =method.invoke(targetObject, args); 
		return obj;
	}
	private void checkPopedom() {
	System.out.println("检查权限:checkPopedom()!"); 
	}
}

通过CGLIB成功创建的动态代理,实际是被代理类的一个子类。那么如果被代理类被标记成final,也就无法通过CGLIB去创建动态代理。

小结

对比jdk实现与cglib实现,1.JDK代理使用的是反射机制实现aop的动态代理,CGLIB代理使用字节码处理框架asm,通过修改字节码生成子类。所以jdk动态代理的方式创建代理对象效率较高,执行效率较低,cglib创建效率较低,执行效率高;2.JDK动态代理机制是委托机制,具体说动态实现接口类,调用其他对象去实现功能,CGLIB则使用的继承机制,具体说被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,如果被代理类有接口,那么代理类也可以赋值给接口。
从代码维护上来讲,cglib与jdk去实现的动态代理,都完成了对原有流程的增强,当原始内容改变时,比如增加一个方法,jdk需要修改接口、实现类;cglib其实只是修改实现类就好,接口没有关系;
另外还有一种实现方式,就是读取jvm中的需要代理的类的class,然后直接操作生成需要的字节码文件,写出或者不写出,用新的字节码去生成代理对象。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赵宁333

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值