java中的动态代理-JDK和cglib

动态代理:在程序运行时,运用反射机制动态创建代理对象。


为了弥补静态代理在开发过程中需要创建过多的代理的缺点,我们可以通过一个代理类完成生成全部代理类的功能,这种方式就是动态代理。

jdk动态代理
下面介绍一下jdk中关于代理的一个接口和一个类:
InvocationHandler接口:

public interface InvocationHandler { 
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; 
} 

Object proxy:指被代理的对象。
Method method:要调用的方法
Object[] args:方法调用时所需要的参数
可以将InvocationHandler接口的子类想象成一个代理的最终操作类。

Proxy类:

public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
                               throws IllegalArgumentException

loader:类加载器
interfaces:得到全部的接口
h:得到InvocationHandler接口的子类实例

与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。

实例:
MyInvocationHandler.java(动态代理类)

public class MyInvocationHandler implements InvocationHandler{
    private Object obj;
    public void setObj(Object obj) {
        this.obj = obj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object result = method.invoke(obj, args);

        maintance();
        return result;
    }
    private void maintance(){
        System.out.println("维护");
    }

}

UserService接口(抽象接口)

public interface UserService {
    public void save();
}

UserServiceImpl .java(真实对象)

public class UserServiceImpl implements UserService{
    @Override
    public void save() {
        System.out.println("保存成功啦");
    }
}

Demo.java(测试类)

public class Demo {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        MyInvocationHandler handler = new MyInvocationHandler();
        handler.setObj(userService);
        UserService usi = (UserService) Proxy.newProxyInstance(
                Demo.class.getClassLoader(),
                userService.getClass().getInterfaces(), 
                handler);
        usi.save();
    }
}

有一点要注意,也就是说再jdk中动态代理要依靠接口来实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。


cglib动态代理

JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

示例代码:
UserServiceImpl.java

public class UserServiceImpl{
    public void save() {
        System.out.println("保存成功啦");
    }
}

MyCglibProxy.java

public class MyCglibProxy implements MethodInterceptor{
    private Object target;

    public Object getInstance(Object target) {  
        this.target = target;  
        Enhancer enhancer = new Enhancer();  
        enhancer.setSuperclass(this.target.getClass());  
        // 回调方法  
        enhancer.setCallback(this);  
        // 创建代理对象  
        return enhancer.create();  
    }  

    @Override
    public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {
        System.out.println("before");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("after");
        return result;
    }
}

Demo.java

public class Demo {
    public static void main(String[] args) {
        MyCglibProxy myCglibProxy = new MyCglibProxy();
        UserServiceImpl userService = (UserServiceImpl) myCglibProxy.getInstance(new UserServiceImpl());
        userService.save();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值