SpringAOP前提知识-动态代理

1:动态代理

相对于静态代理,动态代理在创建代理对象上更加灵活,动态代理类的字节码在程序运行时,由java反射机制动态产生。它会根据需要,通过反射机制在程序运行期间,动态的为目标对象创建代理对象,无需程序员手动编写它的源码。动态代理不仅简化了编程工作,而且提高了软件系统的可扩展性,因为反射机制可以生成任意类型的动态代理类,代理的行为可以代理多个方法,即满足生产需要的同时,又达到代码通用的目的。

2:动态代理实现方式

  1. JDK动态代理:
  2. CGLIB动态代理

3:动态代理特点

  1. 目标对象不固定
  2. 在应用程序执行时动态创建目标对象
  3. 代理对象增强目标对象行为

4:动态代理-JDK动态代理

JDK动态代理的目标对象必须有接口存在。

1:动态代理类

Proxy.newProxyInstance(): 专门完成代理的操作类,可以通过此类为一个接口或多个接口动态的生成实现类,此类提供如下方法:

  1. 当前类加载器:this.getClass().getClassLoader()
  2. 目标角色实现的接口数组:目标角色.getClass().getInterfaces()
  3. InvocationHandler接口实现类:当前代理类实现InvocationHandler接口
    在这里插入图片描述
public class JDKProxy implements InvocationHandler {

    //因为不确定目标角色,所以是Object
    private Object target;

    //通过构造器,将目标角色传入
    public JDKProxy (Object target){
        this.target=target;
    }
    
	 //获取代理类
    public Object getProxy(){

        //获取当前类的类加载器
        ClassLoader classLoader=this.getClass().getClassLoader();
        
        //获取目标角色实现的接口数组
        Class[] interfaces=target.getClass().getInterfaces();
        
        //一个实现InvocationHandler接口的类
        /*
        方式1:
        InvocationHandler invocationHandler=new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return null;
            }
           
        方式2:
        当前类实现InvocationHandler接口
        };*/

        //得到代理实例
        Object proxy=Proxy.newProxyInstance(classLoader,interfaces,this );
        //返回代理实例
        return proxy;
    }

    /**
     * 实现InvocationHandler接口,重写invoke方法。
     * @param proxy:调用该实例的代理实例
     * @param method:目标对象的方法
     * @param args:目标对象方法的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
        //增强目标行为
        System.out.println("方法执行前");

        /*
        调用目标对象的方法
        反射:invoke(Object obj,Object ...args) 
        obj:被调用方法的对象  
        args:被调用方法参数
        */
        
        //使用Object结束方法返回值
        Object invoke = method.invoke(target, args);
       
        //增强目标行为
        System.out.println("方法执行后");

        //目标方法返回值
        return invoke;
    }
}

2:接口
接口1:

public interface BuyHouse {
    void buyHouse();
}

接口2:

public interface BuyCar {
    void buyCar();
}

接口3:带参,有返回值的方法

public interface BuyReturn {
    String buyReturn(String str);
}

3:接口实现类

public class User implements BuyCar,BuyHouse,BuyReturn{

    @Override
    public void buyCar() {
        System.out.println("买车");
    }

    @Override
    public void buyHouse() {
        System.out.println("买房");
    }

    @Override
    public String buyReturn(String str) {
        System.out.println("有参数有返回值的方法");
        return "我是返回值";
    }
}

4:测试动态代理

public class JDKProxyTest {

    public static void main(String[] args) {
        //被代理类对象
        User user=new User();
        
        //获取代理类,被代理类作为参数传入
        JDKProxy jdkProxy=new JDKProxy(user);
        
        //生成代理类对象
        BuyCar buyCar=(BuyCar) jdkProxy.getProxy();
        
        BuyHouse buyHouse=(BuyHouse) jdkProxy.getProxy();
        
        BuyReturn buyReturn=(BuyReturn) jdkProxy.getProxy();
        
        //调用共同行为
        buyCar.buyCar();
        
        buyHouse.buyHouse();
        
        //接收返回值
        String s = buyReturn.buyReturn(new String("我是参数"));
        System.out.println(s);
    }

}

在这里插入图片描述

5:CGLIB动态代理

CGLIB实现原理:为目标类生成一个子类(不能被final修饰类)
在这里插入图片描述
1:引入CGLIB依赖

    <dependencies>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2.2</version>
        </dependency>
    </dependencies>

2:代理类

public class CGLIBProxy implements MethodInterceptor{

    //目标对象
    private Object target;
	
	 //将目标对象作为参数传入
    public CGLIBProxy(Object target){
        this.target=target;
    }

    //获取代理对象
    public Object getProxy(){
        //调用Enhancer的create()方法,生成代理对象
        Enhancer enhancer=new Enhancer();

        //将目标对象设置为当前代理对象的父类
        enhancer.setSuperclass(target.getClass());

        //获取拦截器
       /*
       方式1:
         MethodInterceptor methodInterceptor=new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                return null;
            }
        };
        
        方式2:
        当前类实现接口:implements MethodInterceptor
        */

        //设置拦截器
        enhancer.setCallback(this);

        return enhancer.create();
    }

    /**
     * 每当我们的代理实例被调用 都会执行intercept方法
     * @param o
     * @param method
     * @param objects
     * @param methodProxy
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        //增强行为
        System.out.println("增强行为");
        
        //调用目标对象方法
        Object invoke = methodProxy.invoke(target, objects);
        
        return invoke;
    }
}

3:被代理类

public class People {

    public void eat(){
        System.out.println("吃饭");
    }
}

4:测试CGLIB动态代理

public class CGLIBProxyTest {
    public static void main(String[] args) {
        //目标对象
        People people=new People();
        //代理类
        CGLIBProxy cglibProxy=new CGLIBProxy(people);
        //目标对象的代理对象
        People proxy = (People)cglibProxy.getProxy();
        //调用方法
        proxy.eat();
    }
}

在这里插入图片描述

六:JDK和CGLIB区别

  1. JDK动态代理实现接口,CGLIB动态代理继承思想
  2. JDK动态代理执行效率高于CGLIB动态代理
  3. 如果类实现接口则JDK动态代理,如果没有接口实现则CGLIB动态代理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值