Spring动态代理

 Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。

代理作用:实现无侵入式的代码扩展,在invoke,intercept 中增加其他逻辑

JDK代理:只能对实现了接口的类(如 helloserviceimpl )的类生成代理。

Cglib代理:针对类实现代理,对指定的类生成一个子类,覆盖其中的方法,继承的关系。

默认的策略是如果目标类是接口,则使用JDK动态代理技术,如果目标对象没有实现接口,则默认会采用CGLIB代理。

如果目标对象实现了接口,可以强制使用CGLIB实现代理(添加CGLIB库,并在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)。

java动态代理Cglib 代理和 JDK代理

JDK 代理实现:

public interface HelloService {
void sayHello(String name);
}
public class HelloServiceImpl implements HelloService {
    @Override
    public void sayHello(String name) {
     System.out.println("hello"+name);
        
    }
}

用Java JDK动态代理可以这样做: 

  1. 首先实现一个InvocationHandler,方法调用会被转发到该类的invoke()方法。

  2. 然后在需要使用HelloService 的时候,通过JDK动态代理获取HelloService 的代理对象。

// 1. 首先实现一个InvocationHandler,方法调用会被转发到该类的invoke()方法。
public
class JDKProxy2 implements InvocationHandler { private HelloService hello; @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("hello before"); Object result = method.invoke(hello, args); // Object result = method.invoke(target, args); System.out.println("hello after"); return result; } public JDKProxy2(HelloService hello) { this.hello = hello; } // 2. 然后在需要使用Hello的时候,通过JDK动态代理获取Hello的代理对象。 public static void main(String[] args) {
HelloService hello = (HelloService) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), // 1.类加载器
new Class<?>[] { HelloService.class }, // 2. 代理需要实现的接口,可以有多个
new JDKProxy2(new HelloServiceImpl()));// 3. 方法调用的实际处理者
hello.sayHello("fyp");
//newProxyInstance()会返回一个实现了指定接口的代理对象,对该对象的所有方法调用都会转发给InvocationHandler.invoke()方法
//对代理对象的所有接口方法调用都会转发到InvocationHandler.invoke()方法,在invoke()方法里我们可以加入任何逻辑,记录日志,修改参数等;

}
}

Proxy.newProxyInstance三个参数:

  1.loader: 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载

   2.interfaces: 一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它, 那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了

   3.一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

#HelloService 代理对象的类型信息

class=class jdkproxy.$Proxy0

superClass=class java.lang.reflect.Proxy

interfaces: 

interface jdkproxy.HelloService 

invocationHandler=jdkproxy.JDKProxy2@a09ee92

 

Cglib 代理实现

是实现不是接口的类的动态代理

public class Hello {
    public String sayHello(String str) {
        return "Hello: " + str;
    }
}

通过cglib代理实现的

 
  
public class CglibProxy implements MethodInterceptor{

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
          return proxy.invokeSuper(obj, args);
    }

    public static void main(String[] args) {
        Enhancer  eh=new Enhancer();
        //指定代理对象 
        eh.setSuperclass(Hello.class);
        eh.setCallback(new CglibProxy());
        //调用create()方法得到代理对象
        Hello hello = (Hello)eh.create();
        System.out.println(hello.sayHello("I love you!"));
    }
}
 
  

我们通过CGLIB的Enhancer来指定要代理的目标对象、实际处理代理逻辑的对象,最终通过调用create()方法得到代理对象,对这个对象所有非final方法的调用都会转发给MethodInterceptor.intercept()方法

cglib代理是通过继承类实现的

 
 

# Hello代理对象的类型信息

class=class cglib.Hello$$EnhancerByCGLIB$$e3734e52

superClass=class lh.Hello

interfaces: 

interface net.sf.cglib.proxy.Factory

invocationHandler=not java proxy class

作用:一般用于aop ,添加日志修改参数,对消息进行装饰,以取代原有对象行为的执行

转载于:https://www.cnblogs.com/fanBlog/p/8311019.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值