代理

代理模式分为类

       1、静态代理

       2、动态代理   

静态代理:  

      概述:

                    为目标对象提供一种代理用来控制对该对象的访问

       JDK中的动态代理是通过反射类ProxyInvocationHandler回调接口实现的。但是,JDK中所要进行动态代理的类必须要实现一个接口,也就是说只能对该类所实现接口中定义的方法进行代理,这在实际编程中具有一定的局限性,而且使用反射的效率也并不是很高

       使用CGLib实现动态代理,完全不受代理类必须实现接口的限制,而且CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为finalstatic的方法进行代理,因为CGLib原理是动态生成被代理类的子类

       拓展:ASM 是一个 Java 字节码操纵框架。它可以直接以二进制形式动态地生成 stub 类或其他代理类,或者在装载时动态地修改类。ASM 提供类似于 BCELSERP 之类的工具包的功能,但是被设计得更小巧、更快速,这使它适用于实时代码插装。

        静态代理模式类图如下:

        相关代码示例:

        首先定义一个抽象主题接口Subject

public interface Subject {

	void request();
	
}

        编写真正主题RealSubject

//真正的实现类
public class RealSubject implements Subject {

	@Override
	public void request() {
		System.out.println("real subject execute request");
	}


}

        编写静态代理主题实现类ProxySubject

//代理主题实现类,方法调用还是委托给了真正的实现类,自己只是进行了一些边缘的操作
public class ProxySubject implements Subject {
	
	private RealSubject realSubject;
	
	public ProxySubject(RealSubject realSubject) {
		this.realSubject=realSubject;
	}
	@Override
	public void request() {
		System.out.println("before");
		try {
			realSubject.request();
		}catch(Exception e) {
			System.out.println("ex"+e);
		}finally{
			System.out.println("after");
		}
		
	}

}

        客户端调用代码如下:

//客户端
public class Client {

	public static void main(String[] args) {
		Subject subject= new ProxySubject(new RealSubject());
		subject.hello();
	}
}

 

       静态代理缺点:当需要代理的方法越来越多时,重复的代理类就会越多------产生了动态代理技术

动态代理:

       动态代理有两种实现方式:基于接口代理(JDK代理)和基于继承代理(Cglib代理)

       动态代理:在程序运行时,通过反射机制动态创建一个代理类

        动态代理简易关系图:

        相关代码示例:

        首先定义一个抽象主题接口Subject

public interface Subject {

	void request();
	
}

        编写真正主题RealSubject

//真正的实现类
public class RealSubject implements Subject {

	@Override
	public void request() {
		System.out.println("real subject execute request");
	}


}

          编写动态代理主题实现类JdkProxySubject 

/*
 * 相当于AOP的aspect
 */
public class JdkProxySubject implements InvocationHandler{

	private RealSubject realSubject;
	
	public JdkProxySubject(RealSubject realSubject) {
		this.realSubject = realSubject;
	}
	
	//基于反射,动态的去执行方法
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("before");
		Object result  = null;
		try {
			result=method.invoke(realSubject,args);
		}catch(Exception e) {
			System.out.println("ex"+e);
			throw e;
		}finally{
			System.out.println("after");
		}
		return result;
	}
}

          客户端调用代码如下:

public class Client {

	public static void main(String[] args) {
		Subject subject = (Subject)Proxy.newProxyInstance(Client.class.getClassLoader(), new Class[] {Subject.class},
				new JdkProxySubject(new RealSubject()));
		subject.hello();
	}
}

Cglib动态代理

        原理:动态生成一个要代理类的子类,子类重写要代理的类的所有不是finalstatic的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。它比使用java反射的JDK动态代理要快。

        底层:使用字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。

        缺点:对于finalstatic方法,无法进行代理。

        cglibJDK代理区别
               1:JDK只能针对有接口的类的接口方法进行动态代理
               2:Cglib基于继承来实现代理,无法对staticfinal类进行代理
               3:Cglib基于继承来实现代理,无法对privatestatic方法进行代理

        相关代码展示(不要忘了导入cglib的相关jar包)

        需要被代理的类:

public class RealWorkPerson {

	public void hello() {
		System.out.println("我就是需要被代理的人");
	}
}

        cglib实现的动态代理

public class DemoMethodInterceptor implements MethodInterceptor{

	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		
		System.out.println("before in cglib");
		
		Object result = null;
		try {
			result = proxy.invokeSuper(obj, args); 
		}catch(Exception e) {
			System.out.println("get ex:"+e.getMessage());
			throw e;
		}finally {
			System.out.println("after in cglib");
		}
        //返回执行方法的结果
		return result;
	}

}

        调用的客户端代码如下:

public static void main(String[] args) {
		Enhancer enhancer = new Enhancer();
		//告诉他superclass是谁,即实际的业务对象
		enhancer.setSuperclass(RealWorkPerson.class);
		//要织入的代码(织入代理)
		enhancer.setCallback(new DemoMethodInterceptor());
		//接收生成的代理类
		RealWorkPerson realWorkPerson = (RealWorkPerson)enhancer.create();
		realWorkPerson.hello();
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

快乐的小三菊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值