Java代理

1.简介

java 代理主要为了解决在客户端调用服务时,加入一些前置或后置处理逻辑。
代理类通过提供与委托类相同的接口,在接收到客户端调用后,代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
Java代理主要实现方式:

  • 1.jdk动态代理 (动态AOP)
  • 2.cglib动态字节码生成

2.jdk动态代理

使用Proxy.newProxyInstance生成动态代理

// 接口
public interface IUserDao {
    boolean login(String name, String password) throws RuntimeException;
}
// 实现类
public class UserDaoImpl implements IUserDao {
    @Override
    public boolean login(String name, String password) throws RuntimeException{
        return "wonking".equals(name) && "666".equals(password);
    }
}

动态代理

public class ProxyFactory {

    private ProxyFactory(){
    }

    public static  Object getProxyInstance(final T t){
        return Proxy.newProxyInstance(t.getClass().getClassLoader(), t.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                         // 代理类为委托类做的预处理
                        System.out.println("-----begin transaction-----");
                        Object returnValue=null;
                        try{
                            // 调用委托类本身的实现
                            returnValue=method.invoke(t, args);
                        }catch (Exception e){
                             // 代理类为委托类做的异常处理
                            System.out.println("-----do rollback-----");
                        }
                         // 代理类为委托类做的后处理
                        System.out.println("-----finish transaction-----");
                        return returnValue==null ? false : returnValue;
                    }
                });
    }
}

使用代理:

public class ApplicationProxy {
    public static void main(String[] args) {
        UserDaoImpl target=new UserDaoImpl();
        IUserDao proxy= (IUserDao) ProxyFactory.getProxyInstance(target);
        Object result=proxy.login(null,"666");
    }
}

2.cglib动态字节码生成

public class CglibProxyTest {
   
    public static void main(String[] args) {
        IUserDao userDao = new UserDaoImpl();
        //创建一个织入器
        Enhancer enhancer = new Enhancer();
        //设置父类
        enhancer.setSuperclass(IUserDao.class);
        //设置需要织入的逻辑
        enhancer.setCallback(new LogIntercept(userDao));
        //使用织入器创建子类
        IUserDao proxy = (IUserDao) enhancer.create();
        proxy.login(null,"666");
    }
    
    public class LogIntercept implements MethodInterceptor {

    private Object targetObj;

    public LogIntercept(Object targetObj) {
        this.targetObj = targetObj;
    }

    @Override
    public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        //执行原有逻辑
        Object rev = proxy.invoke(targetObj, args);
        //执行织入的日志
        if (method.getName().equals("login")) {
            System.out.println("记录login日志");
        }
        return rev;
    }
}

3. 自定义类加载器

Javassist是一个开源的分析、编辑和创建Java字节码的类库。

Javassist中最为重要的是ClassPool,CtClass ,CtMethod 以及 CtField这几个类。

  • ClassPool:一个基于HashMap实现的CtClass对象容器,其中键是类名称,值是表示该类的CtClass对象。默认的ClassPool使用与底层JVM相同的类路径,因此在某些情况下,可能需要向ClassPool添加类路径或类字节。
  • CtClass:表示一个类,这些CtClass对象可以从ClassPool获得。
  • CtMethods:表示类中的方法。
  • CtFields :表示类中的字段。
    通过 CtMethods. insertBefore 和 CtMethods. insertAfter 修改类方法实现.
public class ClassLoaderListener  implements Translator {
    public void start(ClassPool pool) throws NotFoundException, CannotCompileException {
    }

    public void onLoad(ClassPool pool, String classname) {
        if (!"com.wulouhua.learn.proxy.service.impl.UserDaoImpl".equals(classname)) {
            return;
        }
        try {
            CtClass cc = pool.get(classname);
            CtMethod m = cc.getDeclaredMethod("login");
            m.insertBefore("{ System.out.println(\"记录日志\"); }");
        } catch (NotFoundException e) {
        } catch (CannotCompileException e) {
        }
    }

    public static void main(String[] args) {
        UserDaoImpl dao = new UserDaoImpl();
        dao.login("wonking","666");
    }
}
public class ClassLoaderBootstrap {
    public ClassLoaderBootstrap() {
    }

    public static void main(String[] args) {
        demo(args);
    }

    static void demo(String[] args) {
        ClassPool cp = ClassPool.getDefault();
        Loader cl = new Loader();

        try {
            cl.addTranslator(cp, new ClassLoaderListener());
            cl.run("com.wulouhua.learn.proxy.service.ways.javassist.ClassLoaderListener", args);
        } catch (NotFoundException var4) {
            var4.printStackTrace();
        } catch (CannotCompileException var5) {
            var5.printStackTrace();
        } catch (Throwable var6) {
            var6.printStackTrace();
        }

    }
}

Translator

你可能感兴趣的:(Java代理)