java · 2024-02-29 0

Cglib 实现多层代理

Cglib代理不要求目标对象实现一个接口

1) 在内存中动态构建子类,注意代理的类不能为final,否则报错java.lang.IllegalArgumentException
2) 目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法

添加maven依赖

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

1.真实角色

public class TeacherDao {

    public void teach() {
        System.out.println("TeacherDao teach");
    }
}

2.代理角色

拦截器里放一个过滤器链,用户在过滤器里拦截多重调用。spring aop 就是使用这样的方式。

public class ProxyFactory {

    // 维护一个目标对象
    private Object target;

    // 构造器传入一个被代理对象
    public ProxyFactory(Object target) {
        this.target = target;
    }

    // 返回一个代理对象,是target对象的代理对象
    public Object getProxyInstance() {
        // 1.创建一个工具类
        Enhancer enhancer = new Enhancer();
        // 2.设置父类
        enhancer.setSuperclass(target.getClass());
        // 3.设置回调函数
        enhancer.setCallback(new MyMethodInterceptor());
        // 2. 创建子类对象,即代理对象
        return enhancer.create();
    }

    class MyMethodInterceptor implements MethodInterceptor {

        // 重写intercept方法,会调用目标对象的方法
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("cglib proxy begin...");
            List<Point> points = Arrays.asList(new Point1(), new Point2());
            Object result = new Chain(target, method, args, points).proceed();
            // Object result = method.invoke(target, args);
            System.out.println("cglib proxy end...");
            return result;
        }
    }

    interface Point {
        Object invoke(Chain chain) throws Throwable;
    }

    public class Chain {
        private Object target;

        private Method method;

        private Object[] arguments;

        private List<Point> points;

        private int index = -1;

        public Chain(Object target, Method method, Object[] arguments, List<Point> points) {
            this.target = target;
            this.method = method;
            this.arguments = arguments;
            this.points = points;
        }

        public Object proceed() throws Throwable {
            if (++index == points.size()) {
                return method.invoke(target, arguments);
            }
            Point point = points.get(index);
            return point.invoke(this);
        }
    }

    public class Point1 implements Point {

        @Override
        public Object invoke(Chain chain) throws Throwable {
            System.out.println("point 1 before");
            Object result = chain.proceed();
            System.out.println("point 1 after");
            return result;
        }
    }

    public class Point2 implements Point {

        @Override
        public Object invoke(Chain chain) throws Throwable {
            System.out.println("point 2 before");
            Object result = chain.proceed();
            System.out.println("point 2 after");
            return result;
        }
    }
}

3.测试

@Test
public void testCglib() {
    TeacherDao teacherDao = new TeacherDao();
    TeacherDao proxyInstance = (TeacherDao) new ProxyFactory(teacherDao).getProxyInstance();
    proxyInstance.teach();
}