Java代理

简单介绍三种代理方式,如果有不清楚的地方可以+QQ:3393055725
Java三种代理方式:静态代理,动态代理(JDK代理),cglib代理

1、静态代理:
静态代理的实现方式很简单,但是用到的不多,静态代理和动态代理使用的前提都是目标对象要实现接口,每个目标对象都要对应一个代理类

//目标对象接口
public interface ITarget {
    void fun();
}
//目标对象
public class Target implements ITarget {

    @Override
    public void fun() {
        System.out.println("调用目标对象方法");
    }
}
//代理类
public class StaticProxy implements ITarget {//实现和目标对象相同的接口
    private ITarget target;//目标对象

    //通过构造函数创建代理对象
    public StaticProxy(ITarget target) {//传参:接口对象
        this.target = target;
    }

    @Override
    public void fun() {
        System.out.println("静态代理开始");
        target.fun();
        System.out.println("静态代理结束");
    }
}
//测试类
public class Test {
    public static void main(String[] args) {
        //目标对象
        ITarget target = new Target();
        ITarget proxy = new StaticProxy(target);
        proxy.fun();
    }
}

2、动态代理
动态代理用到的更多一些,但是目标对象要实现接口,因为动态代理的实现需要传入接口类型, 不需要每个目标对象都对应一个代理类

//省略目标对象的接口和实现类
//...参考静态代理
//动态代理类
public class DynamicProxy {
    //目标对象
    private Object target;
    public DynamicProxy (Object target) {
        this.target = target;
    }
    //生成代理对象
    public Object getProxy() {
        return Proxy.newProxyInstance(//三个参数
            target.getClass().getClassLoader(),//类加载器
            target.getClass().getInterfaces(),//目标对象接口类
            new InvocationHandler(){//事件处理器
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("动态代理开始");
                    Object returnValue = method.invoke(target, args);
                    System.out.println("动态代理结束");
                    return returnValue;
                }
            });
    }
}
//测试类
public class Test {
    ITarget target = new Target();
    ITarget proxy = (ITarget) new DynamicProxy(ITarget target).getProxy();
    proxy.fun(); 
}

3、cglib代理
cglib代理不需要目标对象实现接口,所以当目标对象没有实现接口的前提下可以使用cglib代理,使用cglib代理要引入jar包,在web工程中spring-core.jar文件中包含cglib代理文件
实现原理是为目标对象创建子类对象

// 省略目标对象类,参考静态代理实现类,但是不实现接口即可
// 实现cglib代理
public class CgligProxy implements MethodInterceptor{//实现MethodInterceptor接口
    // 目标对象
    private Object target;
    public CglibProxy(Object target) {
        this.target = target;
    }
    // 为目标对象创建代理对象
    public Object getProxy(){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.serCallback(this);
        return enhancer.create();
    }
    // 重写拦截方法
    @Override
    public Object intercept(Object obj, Method method, Objects[] orgs, MethodProxy proxy) throw Throwable {
        System.out.println("cglib代理开始");
        Object returnValue = method.invoke(target, orgs);
        System.out.println("cglib代理结束");
        return returnValue;
    }

}
// 测试类
public class Test{
    // 目标对象
    Target target = new Target();//这里的不是接口对象,是类对象
    // 代理对象
    Target proxy = (Target) new ProxyFactory(target).getProxy();
    proxy.fun();
}
### Java代理是什么? Java代理是一种设计模式,允许开发者在运行时创建一个代理对象,用来控制对其他对象的访问。这种机制能够拦截对目标对象的方法调用,并在调用前后执行额外的逻辑,例如日志记录、性能监控、权限验证等。Java代理主要分为**静态代理**和**动态代理**两种形式。 静态代理需要在编译时明确指定代理类和目标类的关系,而动态代理则是在运行时通过反射机制动态生成代理类。动态代理的灵活性更高,常用于框架和库的实现中,例如Spring AOP、Hibernate等。 ### Java动态代理的实现方式 Java动态代理主要有两种实现方式:**JDK Proxy** 和 **CGLib**。 1. **JDK Proxy**:这是Java原生支持的一种动态代理方式,它要求目标类必须实现一个接口。JDK Proxy通过`java.lang.reflect.Proxy`类来动态生成代理对象,并使用`java.lang.reflect.InvocationHandler`接口来拦截方法调用[^1]。 - **优点**:无需引入第三方库,仅依赖JDK。 - **缺点**:只能对接口进行代理,不能对类进行代理。 2. **CGLib(Code Generation Library)**:CGLib是一个强大的高性能的代码生成库,它通过继承目标类并生成子类的方式来实现代理功能。因此,CGLib可以对类进行代理,而不仅限于接口[^1]。 - **优点**:支持对类进行代理,适用范围更广。 - **缺点**:需要引入第三方库,生成的代理类可能会增加内存消耗。 ### 如何使用Java动态代理? 以下是一个使用JDK Proxy实现动态代理的简单示例: 1. **定义接口和实现类** ```java // 定义接口 public interface UserService { void addUser(); } // 实现类 public class UserServiceImpl implements UserService { @Override public void addUser() { System.out.println("Adding user..."); } } ``` 2. **创建动态代理处理器** ```java import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class LoggingHandler implements InvocationHandler { private Object target; public LoggingHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before method: " + method.getName()); Object result = method.invoke(target, args); System.out.println("After method: " + method.getName()); return result; } } ``` 3. **创建动态代理对象并调用方法** ```java import java.lang.reflect.Proxy; public class Main { public static void main(String[] args) { UserService userService = new UserServiceImpl(); LoggingHandler handler = new LoggingHandler(userService); UserService proxy = (UserService) Proxy.newProxyInstance( userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), handler ); proxy.addUser(); // 代理对象调用方法 } } ``` 4. **运行结果** ``` Before method: addUser Adding user... After method: addUser ``` 在这个示例中,`LoggingHandler`拦截了`addUser`方法的调用,并在方法执行前后添加了日志记录逻辑。这种机制非常适合用于实现横切关注点(如日志、事务管理等)[^2]。 ### 何时使用Java动态代理Java动态代理适用于以下场景: - **日志记录**:在方法调用前后记录日志信息。 - **性能监控**:统计方法执行时间。 - **权限控制**:在方法执行前检查用户权限。 - **事务管理**:在方法执行前后开启或提交事务。 ### 总结 Java代理是一种强大的编程技术,尤其在动态代理的实现中,JDK Proxy和CGLib各有优劣。JDK Proxy适用于接口代理,而CGLib则适用于类代理。根据具体需求选择合适的代理方式,可以显著提升代码的灵活性和可维护性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值