组件扫描(component scanning):Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件。
特定组件包括:
@Component:基本注解,标识了一个受Spring管理的组件
@Respository:标识持久层组件
@Service:标识服务层(业务层)组件
@Controller:标识表现层组件
对于扫描到的组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写。也可以在注解中通过value属性值标识组件的名称
当在组件类上使用了特定的注解之后,还需要再Spring的配置文件中声明<context:component-scan>:
base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里及其子包中的所有类。
当需要扫描多个包时,可以使用逗号分隔
如果仅希望扫描特定的类而非基包下的所有类,可使用resource-pattern属性过滤特定的类,实例:
<context:component-scan base-package="com.cloud.spring.beans" resource-pattern="autowire/*.class"/>
<context:include-filter>子节点表示要包含的目标类
<context:exclude-filter>子节点表示要排除在外的目标类
- <context:component-scan>下可以拥有若干个<context:include-filter>和<context:exclude-filter>子节点
默认情况下接口类userRepository的bean标识名为实现类userRepositoryImpl的名字。可以通过在@Repository边上以注解的方式进行修改@Repository("userRepository"),修改为接口名bean的名字userRepository。
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans-annotation.xml");
TestObject to = (TestObject) context.getBean("testObject");
System.out.println(to);
UserController userController = (UserController) context.getBean("userController");
System.out.println(userController);
UserService userService = (UserService)context.getBean("userService");
System.out.println(userService);
UserRepository userRepository = (UserRepository) context.getBean("userRepositoryImpl");
System.out.println(userRepository);
}
}
public interface UserRepository {
void save();
}
@Repository
public class UserRepositoryImpl implements UserRepository{
@Override
public void save() {
System.out.println("UserRepositoryImpl Save()");
}
}
<!-- 指定Spring IOC 容器扫描的包 -->
<context:component-scan base-package="com.cloud.spring.beans.annotation"></context:component-scan>
//输出
一月 15, 2020 6:53:56 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@799f7e29: startup date [Wed Jan 15 18:53:56 CST 2020]; root of context hierarchy
一月 15, 2020 6:53:56 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans-annotation.xml]
com.cloud.spring.beans.annotation.TestObject@64485a47
com.cloud.spring.beans.annotation.controller.UserController@25bbf683
com.cloud.spring.beans.annotation.service.UserService@6ec8211c
com.cloud.spring.beans.annotation.repository.UserRepositoryImpl@7276c8cd
修改接口实现类UserRepositoryImpl的bean的名字为UserRepository接口的bean的名字userRepository。
@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository{
@Override
public void save() {
System.out.println("UserRepositoryImpl Save()");
}
}
扫描特定的类而非基包下的所有类,可使用resource-pattern属性过滤特定的类
<context:component-scan base-package="com.cloud.spring.beans.annotation"
resource-pattern="repository/*.class">
</context:component-scan>
UserRepository userRepository = (UserRepository) context.getBean("userRepository");
System.out.println(userRepository);
//输出
com.cloud.spring.beans.annotation.repository.UserRepositoryImpl@289d1c02
<context:include-filter>和<context:exclude-filter>子节点支持多种类型的过滤表达式:
类型 | 示例 | 说明 |
---|---|---|
annotation | com.cloud.XxxAnnotation | 所有标注了XxxAnnotation的类。该类型采用目标类是否标注了某个注解进行过滤 |
assignable | com.cloud.XxxService | 所有继承或扩展XxxService的类。该类型采用目标类是否继承或扩展某个特定类进行过滤 |
aspectj | com.cloud..*Service+ | 所有类名以Service结束的类及继承或扩展它们的类。该类型采用AspecjctJ表达式进行过滤 |
regex | com.\cloud..anno..* | 所有com.cloud.anno包下的类。该类型采用正则表达式根据类的类名进行过滤 |
custom | com.cloud.XxxTypeFilter | 采用XxxTypeFilter通过代码的方式定义过滤规则。该类必须实现org.springframework.core.type.TypeFilter接口 |
不包含<context:exclude-filter>
ApplicationContext context = new ClassPathXmlApplicationContext("beans-annotation.xml");
TestObject to = (TestObject) context.getBean("testObject");
System.out.println(to);
UserController userController = (UserController) context.getBean("userController");
System.out.println(userController);
UserService userService = (UserService)context.getBean("userService");
System.out.println(userService);
UserRepository userRepository = (UserRepository) context.getBean("userRepository");
System.out.println(userRepository);
<context:component-scan base-package="com.cloud.spring.beans.annotation">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
//输出
一月 17, 2020 3:56:00 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@799f7e29: startup date [Fri Jan 17 15:56:00 CST 2020]; root of context hierarchy
一月 17, 2020 3:56:00 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans-annotation.xml]
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'userRepository' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1207)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1078)
at com.cloud.spring.beans.annotation.Main.main(Main.java:28)
包含<context:include-filter>,结合属性use-default-filters="false"使用
<context:component-scan base-package="com.cloud.spring.beans.annotation" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
ApplicationContext context = new ClassPathXmlApplicationContext("beans-annotation.xml");
TestObject to = (TestObject) context.getBean("testObject");
System.out.println(to);
UserController userController = (UserController) context.getBean("userController");
System.out.println(userController);
UserService userService = (UserService)context.getBean("userService");
System.out.println(userService);
UserRepository userRepository = (UserRepository) context.getBean("userRepository");
System.out.println(userRepository);
//输出
一月 17, 2020 4:08:16 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@799f7e29: startup date [Fri Jan 17 16:08:16 CST 2020]; root of context hierarchy
一月 17, 2020 4:08:16 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans-annotation.xml]
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'testObject' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1207)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1078)
at com.cloud.spring.beans.annotation.Main.main(Main.java:19)
assignable
1.exclude
ApplicationContext context = new ClassPathXmlApplicationContext("beans-annotation.xml");
TestObject to = (TestObject) context.getBean("testObject");
System.out.println(to);
UserController userController = (UserController) context.getBean("userController");
System.out.println(userController);
UserService userService = (UserService)context.getBean("userService");
System.out.println(userService);
UserRepository userRepository = (UserRepository) context.getBean("userRepository");
System.out.println(userRepository);
<context:component-scan base-package="com.cloud.spring.beans.annotation">
<context:exclude-filter type="assignable" expression="com.cloud.spring.beans.annotation.repository.UserRepository"/>
</context:component-scan>
//输出
一月 17, 2020 5:17:49 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@799f7e29: startup date [Fri Jan 17 17:17:49 CST 2020]; root of context hierarchy
一月 17, 2020 5:17:50 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans-annotation.xml]
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'userRepository' available
com.cloud.spring.beans.annotation.TestObject@4fb64261
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
com.cloud.spring.beans.annotation.controller.UserController@42607a4f
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1207)
com.cloud.spring.beans.annotation.service.UserService@782663d3
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1078)
at com.cloud.spring.beans.annotation.Main.main(Main.java:28)
2.include
<context:component-scan base-package="com.cloud.spring.beans.annotation" use-default-filters="false">
<context:include-filter type="assignable" expression="com.cloud.spring.beans.annotation.repository.UserRepository"/>
</context:component-scan>
ApplicationContext context = new ClassPathXmlApplicationContext("beans-annotation.xml");
// TestObject to = (TestObject) context.getBean("testObject");
// System.out.println(to);
//
// UserController userController = (UserController) context.getBean("userController");
// System.out.println(userController);
//
// UserService userService = (UserService)context.getBean("userService");
// System.out.println(userService);
UserRepository userRepository = (UserRepository) context.getBean("userRepository");
System.out.println(userRepository);
//输出
一月 17, 2020 5:43:31 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@799f7e29: startup date [Fri Jan 17 17:43:31 CST 2020]; root of context hierarchy
一月 17, 2020 5:43:31 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans-annotation.xml]
com.cloud.spring.beans.annotation.repository.UserRepositoryImpl@396e2f39
网友评论