java动态代理,jdk代理和cglib代理

1.jdk代理

   1.1 接口

public interface BookService {

    public void book();

}

 1.2 实现类

public class BookServiceImpl implements BookService {

    @Override
    public void book() {
        System.out.println("测试");
    }

}

1.3 动态代理类

public class BookProxy implements InvocationHandler {

    private Object target;//这其实业务实现类对象,用来调用具体的业务方法
    /**
     * 绑定业务对象并返回一个代理类
     */
    public Object bind(Object target) {
        this.target = target;  //接收业务实现类对象参数

        //通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用
        //创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this); }
    /**
     * 包装调用方法:进行预处理、调用后处理
     */
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object result=null;

        System.out.println("预处理操作——————");
        //调用真正的业务方法
        result=method.invoke(target, args);

        System.out.println("调用后处理——————");
        return result;
    }
}

 1.4 启动

public class ProxyDemo {
    public static void main(String[] args) {
        BookServiceImpl bookFacadeImpl = new BookServiceImpl();
        BookProxy proxy = new BookProxy();
        BookService bookfacade = (BookService) proxy.bind(bookFacadeImpl);
        bookfacade.book();
    }
}

执行结果

2 cglib动态代理

  测试类复用

 2.1cglib代理类

public class BookProxyCglib implements MethodInterceptor {

    private Object target;//业务类对象,供代理方法中进行真正的业务方法调用

    //相当于JDK动态代理中的绑定
    public Object getInstance(Object target) {
        this.target = target;  //给业务对象赋值
        Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类
        enhancer.setSuperclass(this.target.getClass());  //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
        //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
        enhancer.setCallback(this);
        // 创建动态代理类对象并返回
        return enhancer.create();
    }
    // 实现回调方法
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy  proxy) throws Throwable {
        System.out.println("cglib预处理——————");
        proxy.invokeSuper(obj, args); //调用业务类(父类中)的方法
        System.out.println("cglib调用后操作——————");
        return null;
    }
}

 2.2启动类

public class CglibProxyDemo {
    public static void main(String[] args) {
        BookServiceImpl bookFacadeImpl = new BookServiceImpl();
        BookProxyCglib proxy = new BookProxyCglib();
        BookService bookfacade = (BookService) proxy.getInstance(bookFacadeImpl);
        bookfacade.book();
    }
}

执行结果

 

个人理解:动态代理主要是在原有方法上进行增强,为其他对象提供一种代理以控制对这个对象的访问

以下是区别:

1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP 

3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

如何强制使用CGLIB实现AOP?
 (1)添加CGLIB库,SPRING_HOME/cglib/*.jar
 (2)在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>

JDK动态代理和CGLIB字节码生成的区别?
 (1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类
 (2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
   因为是继承,所以该类或方法最好不要声明成final 

参考:

https://www.cnblogs.com/ygj0930/p/6542259.html

https://www.cnblogs.com/leifei/p/8263448.html

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值