Spring原理(Scope、AOP)

在当前版本的 Spring 和 Spring Boot 程序中,支持五种 Scope

  • singleton,容器启动时创建(未设置延迟),容器关闭时销毁

  • prototype,每次使用时创建,不会自动销毁,需要调用 DefaultListableBeanFactory.destroyBean(bean) 销毁

  • request,每次请求用到此 bean 时创建,请求结束时销毁

  • session,每个会话用到此 bean 时创建,会话结束时销毁

  • application,web 容器用到此 bean 时创建,容器停止时销毁

 每一次刷新request都会刷新

不同浏览器会话都不一样

单例是applicontext Spring容器创建的时候 他就会创建 容器关闭时销毁

多例prototype,每次使用时创建,不会自动销毁,需要调用 DefaultListableBeanFactory.destroyBean(bean) 销毁

singleton 注入其它 scope 失效

单例中注入多例中会 (E是单例)

第二种解决办法

在多例上面配置

第三种运用工厂

 第四种 用容器

从中作梗 不让你直接获取注入对象 

 AOP

AOP 底层实现方式之一是代理,由代理结合通知和目标,提供增强功能

除此以外,aspectj 提供了两种另外的 AOP 底层实现:

  • 第一种是通过 ajc 编译器在编译 class 类文件时,就把通知的增强功能,织入到目标类的字节码中

  • 第二种是通过 agent 在加载目标类时,修改目标类的字节码,织入增强功能

  • 作为对比,之前学习的代理是运行时生成新的字节码

简单比较的话:

  • aspectj 在编译和加载时,修改目标字节码,性能较高

  • aspectj 因为不用代理,能突破一些技术上的限制,例如对构造、对静态方法、对 final 也能增强

  • 但 aspectj 侵入性较强,且需要学习新的 aspectj 特有语法,因此没有广泛流行

反编译之后的结果

 

 利用aspectj的编译器才可以,用maven的编译 别用java本身的

 利用agent 在加载目标类时,修改目标类的字节码,织入增强功能

代理实现AOP(jdk)

public class JdkProxyDemo {

    interface Foo {
        void foo();
    }

    static class Target implements Foo {
        public void foo() {
            System.out.println("target foo");
        }
    }

    public static void main(String[] param) {
        // 目标对象
        Target target = new Target();
        // 代理对象
        Foo proxy = (Foo) Proxy.newProxyInstance(
                Target.class.getClassLoader(), new Class[]{Foo.class},
                (p, method, args) -> {
                    System.out.println("proxy before...");
                    Object result = method.invoke(target, args);
                    System.out.println("proxy after...");
                    return result;
                });
        // 调用代理
        proxy.foo();
    }
}

运行结果

proxy before...
target foo
proxy after..
  • invocationhandler用来实现接口类的方法

  • 在这里method就是foo()

  • jdk 动态代理要求目标必须实现接口,生成的代理类实现相同接口,因此代理与目标之间是平级兄弟关系

jdk版本的代理类会需要接口类 然后还要实现接口的抽象方法,方法里,把AOP加进去

利用反射来执行未增强的方法(让这个目标执行这个方法) 

因为他们实现同一个接口,代理对象就调用实现的方法和目标类类名,利用反射使目标类执行未增强的方法

cglib实现代理

 也要重新实现方法

 因为代理对象是目标的子类,所以也可以调用和目标相同的方法,也就有反射的条件(代理对象调用 经过重写的方法 会传参给这个方法内部 也就是方法method作为参数传了进来 就可以进行反射了)

执行流程是:代理对象调用 经过重写的方法 会传参给这个方法内部 在这个方法里 进行AOP的操作和原目标对象方法的执行

  • cglib 不要求目标实现接口,它生成的代理类是目标的子类,因此代理与目标之间是子父关系

  • 限制⛔:根据上述分析 final 类无法被 cglib 增强

 另两种调用方法,不需要目标对象实例

             Object result = methodProxy.invoke(target, args);(sping用的)
//            Object result = methodProxy.invokeSuper(p, args); 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值