动态代理

2021-06-01  本文已影响0人  bigpeng个人博客

1、什么是代理?

代理是一种软件设计模式,其是通过访问代理对象的方法,而对被代理对象进行操作,相当于加了一个中间环节。这个就好比 商户---->明星经纪人(代理)---->明星这种模式。我们可以不通过直接与明星对话的情况下,而通过明星经纪人(代理)与其产生间接对话。有些时候我们不希望修改已有代码增加功能,这个时候就可以使用代理。 上网翻墙也是同一个意思。

2、静态代理和动态代理

我们根据加载被代理类的时机不同,将代理分为静态代理和动态代理。如果我们在代码编译时就确定了被代理的类是哪一个,那么就可以直接使用静态代理;如果不能确定,那么可以使用类的动态加载机制,在代码运行期间加载被代理的类这就是动态代理,比如RPC框架和Spring AOP机制。

3、静态代理

要点:

/**
 * 描述:
 *
 * @author bigpeng
 * @create 2019-12-02 23:05
 */
public interface Star {

    void show();

    void movie();


}
/**
 * 描述:
 *
 * @author bigpeng
 * @create 2019-12-02 23:06
 */
public class Loudehua implements Star {

    @Override
    public void show() {
        System.out.println("刘德华开个人演唱会");
    }

    @Override
    public void movie() {
        System.out.println("刘德华出演电影");
    }
}
package proxy;

/**
 * 描述:
 *
 * @author bigpeng
 * @create 2019-12-02 23:09
 */
public class LoudehuaProxy implements Star{
    private Star loudehua;

    public LoudehuaProxy(Star loudehua){
        this.loudehua=loudehua;
    }
    @Override
    public void show() {
        System.out.println("经纪人谈好演出事宜");
        System.out.println("经纪人签订合约");
        loudehua.show();
        System.out.println("经纪人收款");
    }

    @Override
    public void movie() {
        System.out.println("经纪人谈好演出事宜");
        System.out.println("经纪人签订合约");
        loudehua.movie();
        System.out.println("经纪人收款");
    }

}
package proxy;

/**
 * 描述:
 *  java 动态代理
 * @author bigpeng
 * @create 2019-12-02 23:15
 */
public class Test {

    public static void main(String[] args) {
        Star star=new Loudehua();
//        Star star=new LoudehuaProxy();
//        star.show();
//        star.movie();
        DynamicProxy dynamicProxy=new DynamicProxy();
        Star o = (Star) dynamicProxy.newInstance(star);
        o.movie();
        o.show();
    }

}

4、动态代理

动态代理在java中有两种实现方式

JDK动态代理

要点:

/**
 * 描述:
 *   动态代理类,实现InvocationHandler接口
 *   动态代理的而必须是接口
 * @author bigpeng
 * @create 2019-12-02 23:28
 */
public class DynamicProxy implements InvocationHandler {

    private Object targetObject;

    public Object newInstance(Object targetObject){
        this.targetObject=targetObject;
        //第一个参数指定产生代理对象的类加载器,需要将其指定为和目标对象同一个类加载器
        //第二个参数要实现和目标对象一样的接口,所以只需要拿到目标对象的实现接口
        //第三个参数表明这些被拦截的方法在被拦截时需要执行哪个InvocationHandler的invoke方法
        return Proxy.newProxyInstance(
                targetObject.getClass().getClassLoader(),
                targetObject.getClass().getInterfaces(),
                this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("经纪人谈好演出事宜");
        System.out.println("经纪人签订合约");
        Object result = method.invoke(targetObject, args);
        System.out.println("经纪人收钱");
        return result;
    }
}

cglib 动态代理

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

被代理类

/**
 * 描述:
 *
 * @author bigpeng
 * @create 2019-12-03 13:32
 */
public class Star {

    public void move(){
        System.out.println("参演电影");
    }

}

代理类

/**
 * 描述:
 *
 * @author bigpeng
 * @create 2019-12-03 13:32
 */
public class StarProxy  implements MethodInterceptor {

    /**
     * 提供代理对象
     * @param object
     * @return
     */
    public Object newInstance(Object object){
        return Enhancer.create(object.getClass(), this);
    }
    /**
     *
     * @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(method.getName());
        System.out.println("签合同");
        Object invoke = methodProxy.invokeSuper(o, objects);
        System.out.println("收钱");
        return invoke;
    }
}

测试类

/**
 * 描述:
 *
 * @author bigpeng
 * @create 2019-12-03 13:35
 */
public class Test {

    public static void main(String[] args) {
        StarProxy starProxy=new StarProxy();
        Star o = (Star) starProxy.newInstance(new Star());
        o.move();

    }

}

spring AOP源码:

区别
JDK动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
CGlib动态代理:利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

区别:JDK代理只能对实现接口的类生成代理;CGlib是针对类实现代理,对指定的类生成一个子类,并覆盖其中的方法,这种通过继承类的实现方式,不能代理final修饰的类

spring 注解式AOP

## 注解方式配置AOP

<context:component-scan base-package="spring.aop"></context:component-scan>

<aop:aspectj-autoproxy/>

package spring.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**

/**
 * @author bigpeng
 * @create 2020-06-28-19:58
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Delete {
    String value();
}
package proxy;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

/**
 * @author bigpeng
 * @create 2020-06-28-20:02
 */
public class MapperProxy implements InvocationHandler {

    public Object getMapper(Class mapper){
        return Proxy.newProxyInstance(mapper.getClassLoader(),new Class[]{mapper},this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Delete delete = method.getAnnotation(Delete.class);
        if(delete!=null){
            String sql = delete.value();
            sql = sql.replaceAll("#\\{\\w+\\}", "?");
            Class.forName("oracle.jdbc.OracleDriver");
            Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "blog",
                    "123456");
            PreparedStatement pstm = conn.prepareStatement(sql);
            for (int i = 0; i < args.length; i++) {
                pstm.setObject(i+1,args[i]);
            }
            int i = pstm.executeUpdate();
            return i;
        }
        return null;
    }
}

public interface UserDao {

    @Delete("delete from t_admin where id=#{id}")
    int delete(int id);
}

public class Test {

    public static void main(String[] args) {
        String sql = "delete from t_admin where  name=#{name} and id=#{id}";
        String s = sql.replaceAll("#\\{\\w+\\}", "?");
        System.out.println(s);
        MapperProxy mapperProxy=new MapperProxy();
        UserDao mapper = (UserDao) mapperProxy.getMapper(UserDao.class);
        int delete = mapper.delete(21);
    }
}
上一篇 下一篇

猜你喜欢

热点阅读