目标,去年一年比较懒吧,所以今年我希望我的知识可以分享给正在奋斗中的互联网开发人员,以及未来想往架构师上走的道友们我们一起进步,从一个互联网职场小白到一个沪漂湿人,一路让我知道分享是一件多么重要的事情,总之不对的地方,多多指出,我们一起徜徉代码的海洋!
我这里做每个章节去说的前提,不是一定很标准的套用一些官方名词,目的是为了让大家可以理解更加清楚,如果形容的不恰当,可以留言出来,万分感激
上节我们说到一些生命周期和创建对象的注解,本节我们看一些扫描相关的注解
1、注解扫描详解
我们一直用过一个xml的标签
<context:component-scan base-package="com.chenxin.spring5.jdk"></context:component-scan>
表示Spring会扫描base-package指定的包以及子包下,进行注解的扫描,来创建对象和注入的。
这个方式自然有点粗犷了,如果我想扫描com.chenxin.spring5.jdk下面的部分包呢,那么这个注解,就显得比较繁琐了,所以Spring衍生出了一个注解,帮助我们更细粒度的控制这个包的扫描情况
先看看Spring用配置文件的方式是怎么处理的
1.1、排除方式
内部有个标签叫做exclude-filter意思是排除哪些你不想要的包,type字段有5个属性
- annotation:排除特定的注解,不进行扫描
- aspectj:排除特定的包下的类上的Spring注解,不进行扫描,通过切入点表达式过滤,注意表达式只能用包切入点,和类切入点,不熟悉多翻翻前面的知识点
- assignable:排除特定的类,不进行扫描
- custom:自定义排除策略,开发中用的更少了;一般会用在框架的底层开发中。比如在开发Springboot的时候,大量使用这个
- regex:正则表达式,进行排除,这个用的很少很少,其实作用和aspectj作用一样的,更多用的是aspectj来实现。
假如我有个需求,我要扫描com.chenxin.spring5.jdk下的一些包,但是我想排除某个类,让Spring不扫某个类,比如就是com.chenxin.spring5.jdk.User,那么我们就可以这么写
<context:component-scan base-package="com.chenxin.spring5.jdk"> <context:exclude-filter type="assignable" expression="com.chenxin.spring5.jdk.User"/> </context:component-scan>
这样就可以做到我不想扫包下的特定类!!
假如我现在又有一个需求,我要扫描com.chenxin.spring5.jdk下的一些包,但是我想排除特定的注解,比如我不想扫一些@Service的一些类
<context:component-scan base-package="com.chenxin.spring5.jdk"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/> </context:component-scan>
假如我又有一个需求,我要扫描com.chenxin.spring5下的一些包,但是我想排除某些包或者子包下的类上具有Spring的注解,不进行扫描,com.chenxin.spring5.jdk..*表示下面的包及其子包(包切入点)
<context:component-scan base-package="com.chenxin.spring5"> <context:exclude-filter type="aspectj" expression="com.chenxin.spring5.jdk..*"/> </context:component-scan>
如果是类切入点表达式呢,*..User表示当前com.chenxin.spring5所有的包及其子包下,只要有User类,就不扫进去
<context:component-scan base-package="com.chenxin.spring5"> <context:exclude-filter type="aspectj" expression="*..User"/> </context:component-scan>
注意细节:
排除策略可以叠加使用的,比如我可以排除某个特定类,也可以同时排除某个包,举个例子哈,比如我想要排除这个com.chenxin.spring5.bean.User这个类不被扫描,又想排除这个com.chenxin.spring5.jdk..*这个包及其子包下的所有的类
<context:component-scan base-package="com.chenxin.spring5"> <context:exclude-filter type="assignable" expression="com.chenxin.spring5.bean.User"/> <context:exclude-filter type="aspectj" expression="com.chenxin.spring5.jdk..*"/> </context:component-scan>
1.2、包含方式
包含方式决定了Spring要扫描哪些注解,进而完成对象的创建
和排除方式不同的地方有两点
- use-default-filters="false",作为这个属性,Spring是有个默认策略,就是你写了base-package的包路径,会默认扫你当前包和子包下的所有注解,而这个属性默认是true,表示使用默认的过滤,但是目前因为是要包含某些包下的注解要被扫描,而如果你按照Spring默认策略,就等同于扫了所有包,包含了所有包,你就不能够定制化你的需求;所以就不能按照Spring默认策略扫包和子包的条件了,因为我只想让Spring扫描我特定需要的注解,别按照默认的方式了。所以让默认扫描失效,给false
context:include-filter:指定你需要扫描的那些注解
<context:component-scan base-package="com.chenxin.spring5" use-default-filters="false"> <context:include-filter type="" expression=""/> </context:component-scan>
type类型也和上面的排除是一样的,只是语义是相反的
- annotation:包含特定的注解,进行扫描
- aspectj:包含特定的包下的类上的Spring注解,进行扫描,通过切入点表达式过滤,注意表达式只能用包切入点,和类切入点,不熟悉多翻翻前面的知识点
- assignable:包含特定的类,进行扫描
- custom:自定义包含策略,开发中用的更少了;一般会用在框架的底层开发中。比如在开发Springboot的时候,大量使用这个
- regex:正则表达式,这个用的很少很少,其实作用和aspectj作用一样的,更多用的是aspectj来实现。
这个包含的例子我就不多做解释了,和上面相反,这个感兴趣可以自己试试。效果不错的!
到这,注解扫描的详解,我就解释完了,更多的是练习练习再练习,反复反复再反复。
2、对注解开发的思考
- 配置互通:Spring注解配置和配置文件的配置,是可以互通的,比如我们UserDaoImpl用@Repository创建,而UserServiceImpl用xml创建,那么在xml的bean ref标签就可以引用userDaoImpl这个bean的id,反之也是可以的
- 什么情况下用注解,什么情况下用xml方式呢?是不是我们以后一旦用了注解,就可以彻底取代xml的方式了吗?
对于我们开发中,这些注解@Repository,@Service,@Autowired等等这些注解都是我们开发的时候,自己加上去的,这些都是我们自己开发需求,但是你很有可能会接触一些代码,比如SqlsessionFactoryBean,或者MapperScannerConfigure,这些类不是你写的,那你有没有机会在这些类上加上@Component,@Service这些注解呢?显然是没机会的,而这些类要是想创建他们的对象,应该怎么办呢?我们只能用bean标签了。
所以使用注解的情况只有一种:在程序员开发的类型上,可以加入对应的注解,进行对象的创建
对于应用其他非程序员开发的类型时候,还是需要bean标签进行配置!!
到此,基础注解部分我们算告一段落了,下一节我们更新高级注解部分!!!