Spring AOP理解

本文深入探讨了AOP(面向切面编程)的概念及其在AspectJ和Spring框架中的实现方式,对比了编译时、类加载时及运行时织入的区别。同时,详细解析了CGLIB、JDK动态代理的工作原理,以及它们在Spring AOP中的应用策略。通过具体代码示例,展示了如何使用JDK动态代理和CGLIB实现对方法的增强。

AspectJ是编译时织入

AspectJ 5+是类加载时织入

Spring AOP是运行时织入

 

【动态】CGLIB、JDK动态代理、Spring AOP

【静态】AspectJ、JDK静态代理

 

    静态代理的缺点: 

     1)一个代理类只为一个接口服务,如果要代理的接口很多,势必要为每一种接口都进行代理,静态代理在程序规模稍大时就无法胜任了。 
     2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。

 

cglib通过继承的方式实现代理类(Enhancer类的setSuperclass方法),通过Enhancer类的setSuperclass方法织入

JDK只能针对有接口的类的接口方法进行动态代理

/**
* JDK代理演示
*/
interface Message {
    void send();
}

class MessageImp implements Message {

    @Override
    public void send() {
        System.out.println("send message");
    }
    public void send2() {
        System.out.println("send222222222222222222222");
    }
}

public class DynamicProxy implements InvocationHandler {

    /**
     * 真实的业务对象
     */
    private Object target;

    /**
     * 增强的方法
     */
    private boolean connect() {
        System.out.println("[消息代理],进行发送消息之前的连接");
        return true;
    }

    /**
     * 增强的方法
     */
    private void close() {
        System.out.println("[消息代理],关闭连接");
    }

    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }

    /**
     * @param proxy  需要代理的对象
     * @param method 要执行的方法的名称
     * @param args   要执行的方法的参数
     * @return 方法的返回值
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object returnData = null;
        if (this.connect()) {
            returnData = method.invoke(this.target, args);
            this.close();
        }
        return returnData;
    }

    /**
     * 客户端
     * @param args
     */
    public static void main(String[] args) {
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
        Message message = (Message) new DynamicProxy().bind(new MessageImp());
//      MessageImp messageImp = (MessageImp) new DynamicProxy().bind(new MessageImp()); error 无法转换成MessageImp类型
        message.send();
//      messageImp.send(); error
//      messageImp.send2(); error
    }
}

cglib基于继承来实现代理,无法对static,final类进行代理,也无法对private,static方法进行代理
 

Spring AOP中代理方式的选择:

如果目标对象实现了接口,则默认采用JDK动态代理

如果目标对象没有实现接口,则采用cglib动态代理

如果目标对象实现了接口,且强制cglib代理,则使用cglib代理(设置如下)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值