Java框架Spring进阶详解注解使用大全 更高效开发的模式

在项目开发中如果我们通过在xml文件内部注册bean给spring容器的形式,那么如果需要注册的bean过多怎么办?一千行一万行的代码非常不便于阅读,因为我们除了注册bean之外还需要在主配置文件中配置其他的东西,那么配置信息就更难以阅读了。于是spring提供了一种早期的分布式文件系统思想,我们将所有bean标签单独移动到一个xml中,然后在applicationConetxt.xml引入这个xml文件,下面请看代码是如何实现的。

5777390-22da5bec86f34ec8.png

可以看到主配置文件已经非常干净了,那么bean标签都去哪里了呢?别急,先看图中红框标识出的是什么呢.ContextModel,内容model,这里是一个标签的载入顺序,最先载入的是我们xml的description部分,也就是xsd约束。接下来,载入的是import标签,该标签能够将其他配置文件关联至本页面,相当于这里创建了一个另一个xml的引用,它的属性只有一个,就是resource,里面写需要引入的配置稳健的相对路径,这样看起来就清爽了许多。

那么我觉得在xml中配置bean太过于麻烦了,有没有其他简单的方法?有,spring同时提供了一种通过注解来创建bean,为属性注入的方式。先看上图的<context:component-scan>标签,context环境,component组件,scan扫描。该标签用于扫描项目中的注解,如果扫描到这个注解,将会启用注解的功能,如果注解没有被扫描到,那注解就是失效的。本次使用基于包的方式扫描,就是扫描包下子孙包中的注解,通常的格式为com.projectName.xxx ,我这里使用..路径表示扫描src下的任意子孙包。在applicationContext.xml中配置扫描路径后接下来看看注解的用法

5777390-278d4c0daa55ab50.png

这是user注册bean的配置,这么大一坨,下面看看通过注解注册有多少行代码

5777390-3589a98a9c811642.png

答案一目了然,只有四个单词,替代了整整一大坨的xml配置方式,注解也是现在的主流开发方式。下面让我们来认识一下这些注解是什么意思,@Component: 组件,在类名上方使用此注解能够将该类注册到Sping容器中,从而创建实例,同时结合spring的分成思想,又提供了另外三个与@Component功能一模一样的注解,分别用于三层中。*@Controller :WEB 层,@Service :服务层@Repository :持久层,这三个注册除了能够Component本身功能外,还起到一定的标识作用,表名该类的用途。

注解对IOC的支持结束后,下面看看对DI怎么使用。我们使用@value注解对基本数据类型进行注入,使用起来比较简单在括号内写入需要注入的值即可,但是注入的值类型必须符合变量类型,就是说如果变量是个int类型,不能写String进去。那么对象类型该怎么注入呢?使用@Autowired,该标签通过对象的类型注入实例,实现原理是:比如我变量类型为User,那么spring会在容器中寻找类型为user的实例,找到了就注入到变量中。它有一个要求,注入的对象必须是被注册到spring容器中的bean,否则无法完成注入。那么如果出现多个与变量类型匹配的对象spring应该注入哪一个呢?见下图

那么这里我们使用scope标签就User2的作用范围指定为prototype多例,会发生什么呢?spring就会不知道应该为User1中变量注入哪一个对象了,这时spring提供了两种解决方案

5777390-7b84a87ee0b8fb25.png

组合使用@Autowired@Qualifier标签,@Qualifier标签能够在@Autowired给的类型内部指定变量名称。而@Resource能够直接指定需要注入的变量名称,@Resource一个标签能够替代@Autowired@Qualifier两个标签,所以建议在注入对象为单例情况下,建议使用@Autowired标签,可能为多例的情况下使用@Resource标签。下面执行以下程序打印对象看看结果

5777390-6161e8b715a5ab6c.png

程序正确执行了,但是红框标出来的值缺不是我之前在上图通过@Value注入的值,这是为什么呢?

5777390-3997f97cae8b286a.png

大家看到@PostConstruct和@PreDestroy注解,会想到这两个做什么的呢?这两个注解就像鱼bean标签中的,init-method和destroy-method,原来bean中的任一属性都有相对应的注解来实现,不过上面输出了我设置的当前系统时间,说明了什么?是我的注解@value没有生效吗,并不是,而这里恰恰说明一个问题,init方法是在spring对phoneNumber变量赋值后才执行的,为了证实这一猜想我们进行如下测试

5777390-c929fd7e1b3ca66f.png

在对phoneNumber赋值之前打印,以证实@value注解是否生效,可以猜测一下执行结果看看下图是否如你所想

5777390-dd4115337e828c4d.png

看到打印结果证明@value注解正常执行,init方法确实是在spring注入之后执行。那么为什么为执行了三次init方法呢?下面我将会标识出,对user2进行访问的代码

5777390-3273d426efe6589b.png

此处创建User2引用并通过@Resource注入时,创建了一个user2实例,执行了一次init方法。

5777390-bef67773024e1dd8.png

此处创建User2引用并通过@Resource注入时,创建了一个user2实例,执行了一次init方法。不过在我的User3类中@Resource注解并没有指定name,为什么也能够完成注入呢?@Resource标签在不指定name时,默认寻找类型名称首字母小写的变量。比如我有一个类叫YUD,那么@Resource不指定name时,默认名寻找yUD的变量。

5777390-81d0caed20632a7e.png

最后一次对User2的访问xml中对集合进行注入时,注入了一个user2,也就是如果User2的范围是prototype时,每次访问都会生成新的对象,而scope为singleton单例时,每次访问都为同一对象,init方法也会只执行一次。

那么当我们手动关闭容器时,它的destory方法会发生怎么样的变化呢?

5777390-0caeea20b24f6360.png

手动关闭容器时,当bean的范围为单例singleton时,destory方法会执行一次.当scope为prototype多例时,destory方法不会被执行,也就是说只有单例的情况下spring容器才会回收bean对象,否则由Jvm进行回收。

此外补充一点,在spring环境下有些人的@Resource标签可能无法使用,因为这个标签是J2EE的标签,我们需要通过maven引入javax拓展包下的annotation依赖即可。

5777390-727aed6589444f20.png

以上就是spring通过注解的方式进行IOC,DI操作了,是不是很方便呢?请在评论区留下你的看法把!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值