组件扫描(component scanning):Spring能够从classpath下自动扫描,侦测和实例化具有特定的注解的组件。
—@Component:基本注解,标识了一个受Spring管理的组件
—@Respository:标识持久层组件,具有将数据库操作抛出的原生异常翻译转化为Spring的持久层异常的功能。
—@Service:标识服务层(业务层)组件
—@Controller:标识表示层组
对于扫描到的组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写,也可以在注解中通过value属性表示组件的名称@Repository(value = "userRepository")。比如UserService创建Bean默认的名字就是userService。
下面来编写具体的实现代码:
TestObject类使用@Compent注解:
1 @Component 2 public class TestObject { 3 }
UserService类使用@Service注解
1 @Service 2 public class UserService { 3 public void add() { 4 System.out.println("UserService add..."); 5 } 6 }
UserRepository接口
1 public interface UserRepository { 2 public void save(); 3 }
UserRepositoryImpl实现类使用@Repository
1 @Repository 2 public class UserRepositoryImpl implements UserRepository { 3 4 public void save() { 5 System.out.println("UserRepository Save。。。。"); 6 } 7 }
UserController使用@Controller
1 @Controller 2 public class UserController { 3 public void execute() { 4 System.out.println("UserController execute...."); 5 } 6 }
在类上加完注解之后,SpringIOC容器并不能直接去管理我们的bean,因为注解本身和xml一样只是起一个配置作用,Spring需要对指定类路径下的包进行扫描:
1 <context:component-scan base-package="com.wzy.annotation"/>
编写一个测试类,来测试标识了这些注解的类是否被添加到SpringIOC容器中:
1 public static void main(String[] args) { 2 ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml"); 3 UserController userController = (UserController) ctx.getBean("userController"); 4 System.out.println(userController); 5 6 UserService userService = (UserService) ctx.getBean("userService"); 7 System.out.println(userService); 8 9 UserRepository userRepository = (UserRepository) ctx.getBean("userRepositoryImpl"); 10 System.out.println(userRepository); 11 12 TestObject testObject = (TestObject) ctx.getBean("testObject"); 13 System.out.println(testObject); 14 }
输出结果:我们可以观察到可以打印出这些bean,并且也可以验证他们的bean的id确实是,类的名字第一个字母小写。
在使用<context:component-scan>注意一下几个关键点:
—base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里及其子包中的所有类。
—当需要扫描多个包时,可以使用逗号分隔。
—如果仅希望扫描特定的类而非基类包下的所有类,可以使用resource-pattern属性过滤特定的类。
1 <context:component-scan base-package="com.wzy.annotation" resource-pattern="repository/*.class"> 2 </context:component-scan>
在<context:component-scan>标签下有两个子标签:<context:include-filter>和<context:exclude-filter>:
<context:exclude-filter>: 子节点表示要排除在外的目标类
两个子标签支持多种类型的过滤表达式,以下五种模式:最常用的是前两种。
首先来看annotation过滤表达式的用法,首先看这个表达式的名字,说明它过滤的是注解,也就包含或者不包含某种注解,这里要注意的是指定包含哪些子节点的组件,该子节点需要user-default-filters 配合使用,否则是使用默认的过滤器,会扫描全部的组件。
1 <!--不包含什么: <context:exclude-filter子节点指定排除哪些指定表达式的组件--> 2 <context:component-scan base-package="com.wzy.annotation"> 3 <!--不包含repository--> 4 <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/> 5 </context:component-scan> 6 7 <!--<context:include-filter 指定包含哪些子节点的组件,该子节点需要user-default-filters 配合使用,否则是使用默认的过滤器,会扫描全部的组件--> 8 <context:component-scan base-package="com.wzy.annotation" 9 use-default-filters="false"> 10 <!--包含repository--> 11 <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/> 12 </context:component-scan>
下面来看assignable表达式的用法,它过滤的是某个类以及它的子类,如果设置没有扫描某种bean,我们依然从容器中获取,那么就会抛出异常。
1 <context:component-scan base-package="com.wzy.annotation"> 2 <!--不包含repository--> 3 <context:exclude-filter type="assignable" expression="com.wzy.annotation.repository.UserRepository"/> 4 </context:component-scan> 5 6 <context:component-scan base-package="com.wzy.annotation" use-default-filters="false"> 7 <!--只包含repository--> 8 <context:include-filter type="assignable" expression="com.wzy.annotation.repository.UserRepository"/> 9 </context:component-scan>
原文:https://www.cnblogs.com/fengyun2019/p/10843727.html