java代理总结

参考博文[https://www.jianshu.com/p/471c80a7e831]
代理分为3种

  1. jdk静态代理
  2. jdk动态代理
  3. cglib动态代理

jdk静态代理

实现过程:

  1. 创建一个接口
public Interface HelloInterface(){
    void sayHello();
}

2.创建被代理的类实现该接口并实现接口中的抽象方法

public class Hello implements HelloInterface{

    @Override
    public void sayHello(){
        System.out.println("Hello Eakon");
    }
}

3.创建一个代理类,同时也实现这个接口,在代理类中持有一个被代理对象的引用,之后在代理类方法中调用该对象的方法。

public class HelloProxy implements HelloInterface{
private HelloInterface interface=new Hello();

    @Override
    public void sayHello(){
        System.out.println("Before invoke sayHello");
        interface.sayHello();
        System.out.println("After invoke sayHello");
    }
}

测试代码:

public class Client {

    public static void main(String[] args){
        HelloProxy helloProxy=new HelloProxy();
        helloProxy.sayHello();
    }
}

运行结果:

Before invoke sayHello
Hello Eakon
After invoke sayHello

代理类HelloProxy为被代理类Hello预处理过滤,之后将消息转发给被代理类,之后还能进行消息的后置处理。被代理类和代理类存在依赖关系。代理类本身不实现服务,而是通过调用被代理类的方法来提供服务。
缺点:静态代理只能为一个类服务,如果需要为多个类服务(需要代理的类很多),需要编写大量的代理类,比较繁琐。

jdk动态代理

代理类

public class HelloProxy implements InvocationHandler{
	
	private Object subject;
	
	public HelloProxy(Object subject) {
		super();
		this.subject = subject;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("Before invoke"+method.getName());
		method.invoke(subject, args);
        System.out.println("After invoke"+method.getName());
		return null;
	}

}

测试代码:

public class Client {

	public static void main(String[] args) {
		Hello hello=new Hello();
		InvocationHandler handler=new HelloProxy(hello);
		HelloInterface helloInterface=(HelloInterface) Proxy.newProxyInstance(
				handler.getClass().getClassLoader(), hello.getClass().getInterfaces(), 
				handler);
		helloInterface.sayHello();
	}

}

也是基于基本接口实现的。通过接口指向实现类实例的多态方式,可以将具体实现与调用解耦,便于后期的维护。

jdk动态代理和静态代理区别:
相同点:都要创建代理类,代理类都要实现接口
不同点:静态代理中,需要对接口,被代理类创建代理类,在编译前就需要代理类实现和被代理类相同的接口,并且直接在实现的方法中调用被代理类相应的方法;但是,动态代理中,我们不知道对哪个接口哪个被代理类创建代理类,因为代理类的创建是利用反射在运行时。

spring中用到是jdk动态代理和cglib动态代理。动态代理天生就是为aop而生,如果没有动态代理,需要写一些重复的逻辑。有了动态代理,结合反射,可以很轻松的实现接口级别的aop 。

如果,没有接口,想要实现代理,使用cglib动态代理。

cglib动态代理

首先引入cglib依赖

 <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>3.1</version>
    </dependency>

被代理类

public class HelloImpl {
	void sayHello() {
		System.out.println("hello cglib");
	}
}

代理类实现MethodInterceptor接口

public class HelloMethodInterceptor implements MethodInterceptor{
	public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
		System.out.println("Before"+arg1.getName());
		Object object=arg3.invokeSuper(arg0, arg2);
		System.out.println("After"+arg1.getName());
		return object;
	}
}

测试代码:

public class App 
{
    public static void main( String[] args )
    {
        Enhancer enhancer=new Enhancer();
        enhancer.setSuperclass(HelloImpl.class);//继承被代理类
        enhancer.setCallback(new HelloMethodInterceptor());//设置回调
        HelloImpl helloService=(HelloImpl) enhancer.create();//生成代理类对象 
        helloService.sayHello();//调用该方法被我们实现的方法拦截器拦截
    }
}

jdk代理要求被代理的类必须实现接口,但cglib动态代理没这样的强制要求,它会让生成的代理类继承被代理类,并在代理类中对代理方法进行强化处理(前置处理和后置处理)。
代理类对象是由Enhancer(cglib的字节码增强器,可以方便的对类进行扩展)创建的。
缺点:不能为final的类或方法进行代理。因为final的类或方法不能继承。

代理方式实现优点缺点特点
jdk静态代理代理类和被代理类实现同一接口,并且在代理类中需要持有被代理对象的引用实现容易实际使用中,需要声明硬编码接口,浪费存储空间且效率低
jdk动态代理代理类和被代理类实现同一接口,代理类实现InvocationHanlder接口,重写invoke方法,在invoke中进行增强处理不需要编码接口,代码重用率高只能代理实现了接口的被代理类使用反射进行方法的调用
cglib动态代理代理类将被代理类作为自己的父类,并为其中的非final方法创建两个方法,一个是与被代理类方法签名相同的方法,它在方法中通过super调用被代理的方法;另一个是代理类独有的方法,它会判断是否实现了MethodInterceptor接口的对象,若存在调用intercept方法进行代理可以对类和接口进行代理,并且被代理类无须实现接口不能对final的类或方法进行代理将全部方法存入一个数组中,通过数组索引直接进行方法调用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值