spring中注解及原理

目录

 

一、 IoC

二、容器实现依赖注入

注解的原理:


一、 IoC

IoC:控制反转:某一接口实现类的选择控制权从调用类中移除,转交给第三方决定,即由Spring容器借由Bean配置来进行控制。eg:由导演控制剧本、角色和演员的依赖关系,将剧本对演员的依赖解耦。

那么通过控制反转(IOC)是怎么实现减少耦合的呢?总结网上的说法,从两个角度出发

 1、控制反转

① 软件系统在没有引入IoC容器之前,对象A依赖对象B,那么A对象在实例化或者运行到某一点的时候,自己必须主动创建对象B或者使用已经创建好的对象B,其中不管是创建还是使用已创建的对象B,控制权都在我们自己手上。 

② 如果软件系统引入了Ioc容器之后,对象A和对象B之间失去了直接联系,所以,当对象A实例化和运行时,如果需要对象B的话,IoC容器会主动创建一个对象B注入到对象A所需要的地方。

③ 通过前面①②的对比,可以看到对象A获得依赖对象B的过程,由主动行为变成了被动行为,即把创建对象交给了IoC容器处理,控制权颠倒过来了,这就是控制反转的由来!

注:在控制反转与解耦过程中使用了设计模式中的工厂模式。

工厂模式

工厂模式是指当应用程序中甲组件需要乙组件协助时,并不是在甲组件中直接实例化乙组件对象,而是通过乙组件的工厂获取,即该工厂可以生成某一类型组件的实例对象。在这种模式下,甲组件无需与乙组件以硬编码的方式耦合在一起,而只需与乙组件的工厂耦合,那么这样的话,通过依赖注入就可以完全不用关心对象的生命周期,什么时候被创建,什么时候销毁,只需直接使用即可,对象的生命周期由提供依赖注入的框架来管理,从而,让使用框架者,可以将重心完全放到业务逻辑处理的开发上。

2、spring之aop

① 在业务系统里除了要实现业务功能之外,还要实现如权限拦截、性能监控、事务管理等非业务功能。
通常的作法是非业务的代码穿插在业务代码中,从而导致了业务组件与非业务组件的耦合。

② aop面向切面编程,就是将这些分散在各个业务逻辑代码中的非业务代码,通过横向切割的方式抽取到一个独立的模块中,从而实现业务组件与非业务组件的解耦。

IoC通过DI(依赖注入)实现:让调用类对某一接口实现类的依赖关系由第三方(容器或协助类)注入,以移除调用类对实现类的依赖。

注入方法:

1.构造函数注入。 将接口实现类通过调用类的构造函数的参数传入。

public class MovieLister {
    private MovieFinder finder;

    public MovieLister(MovieFinder finder) {
        this.finder = finder;
    }
    ...
}

2.属性注入。 (演员不是每场戏都要出现,在需要的时候出现即可)通过Setter方法传入。

public class MovieLister {
    s...
    public void setFinder(MovieFinder finder) {
        this.finder = finder;
    }
}

3.通过接口注入。 需要额外的接口声明而且和属性注入无本质区别,不提倡。

public interface InjectFinder {
    void injectFinder(MovieFinder finder);
}

class MovieLister implements InjectFinder {
    ...
    public void injectFinder(MovieFinder finder) {
      this.finder = finder;
    }
    ...
}

二、容器实现依赖注入

Spring通过配置文件或注解描述类与类之间的依赖关系,自动完成类的初始化和依赖注入。

通过注解注入bean,就是实例化依赖类的方式,这也是为什么要将@Service和@Repository放到实现类上面而不是接口类上面,接口只是一个规范,需要各种实现类去实现这个接口,我们要用的就是这些实用类的方法。

注入的方式有@Recource和@Autowired

@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。

@Resource有两个属性是比较重要的,分别是name和type,spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。

@Resource装配顺序

  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
  2. 如果指定了name,则从上下文中查找名称(id匹配的bean进行装配,找不到则抛出异常。
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常。
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配,如果没有匹配,则回退为一个原始类型(UserDao)进行匹配,如果匹配则自动装配。

当指定了@service的name值时, 在@Resource中要么不指示,如果指示的话,则要与之相对应。

当没有指定@service的name值是,在@Resource中随意。但是前提是,实现该接口的只有这一个类。

所以,建议是最好在@service和@Resoure中同时指定名称,并且做到一一对应。

如果采用@Autowired来注解,则同样无需指定name属性,若是实现该接口有多个类,则需要通过@Qualifier来做区分

注解的原理:

对于注解Test,如下,如果对AnnotationTest类进行注解,则运行时可以通过AnnotationTest.class.getAnnotation(Test.class)获取注解声明的值,从上面的句子就可以看出,它是从class结构中获取出Test注解的,所以肯定是在某个时候注解被加入到class结构中去了。

@Test("test")
public class AnnotationTest {
  public void test(){
  }
}

从java源码到class字节码是由编译器完成的,编译器会对java源码进行解析并生成class文件,而注解也是在编译时由编译器进行处理,编译器会对注解符号处理并附加到class结构中,根据jvm规范,class文件结构是严格有序的格式,唯一可以附加信息到class结构中的方式就是保存到class结构的attributes属性中。我们知道对于类、字段、方法,在class结构中都有自己特定的表结构,而且各自都有自己的属性,而对于注解,作用的范围也可以不同,可以作用在类上,也可以作用在字段或方法上,这时编译器会对应将注解信息存放到类、字段、方法自己的属性上。

在我们的AnnotationTest类被编译后,在对应的AnnotationTest.class文件中会包含一个RuntimeVisibleAnnotations属性,由于这个注解是作用在类上,所以此属性被添加到类的属性集上。即Test注解的键值对value=test会被记录起来。而当JVM加载AnnotationTest.class文件字节码时,就会将RuntimeVisibleAnnotations属性值保存到AnnotationTest的Class对象中,于是就可以通过AnnotationTest.class.getAnnotation(Test.class)获取到Test注解对象,进而再通过Test注解对象获取到Test里面的属性值。

注解被编译后的本质就是一个继承Annotation接口的接口,所以@Test其实就是“public interface Test extends Annotation”,当我们通过AnnotationTest.class.getAnnotation(Test.class)调用时,JDK会通过动态代理生成一个实现了Test接口的对象,并把将RuntimeVisibleAnnotations属性值设置进此对象中,此对象即为Test注解对象,通过它的value()方法就可以获取到注解值。

参考:

https://blog.csdn.net/qq_35923749/article/details/77159213

https://www.jb51.net/article/125696.htm

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值