版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011171125/article/details/85719509
Spring入门学习(基于注解的方式配置Bean)
指定SpringIOC容器扫描包
分别创建repository,service,controller
层
- 添加类
TestObject
,使用@Component
注解标注为组件:@Component public class TestObject { }
- 创建
repository
层相关类:public interface UserRepository { void save(); }
UserRepositoryImpl
实现UserRepository
接口,并在类上添加注解@Repository
:@Repository public class UserRepositoryImpl implements UserRepository { @Autowired(required=false) private TestObject testObject; @Override public void save() { System.out.println("UserRepositoryImpl Save..."); System.out.println(testObject); } }
- 创建
service
层相关类,并在类上添加@Service
注解:@Service public class UserService { private UserRepository userRepository; @Autowired public void setUserRepository(UserRepository userRepository) { this.userRepository = userRepository; } public void add(){ System.out.println("UserService add..."); userRepository.save(); } }
- 创建
controller
层,添加注解@Controller
:@Controller public class UserController { @Autowired private UserService userService; public void execute() { System.out.println("UserController execute..."); userService.add(); } }
- 创建
<!-- 指定SpringIOC容器扫描的包 --> <!-- 可以通过resource-pattern指定扫描的资源 --> <context:component-scan base-package="com.fafa.spring.bean.annotation"></context:component-scan>
- 新建测试类:
测试结果:public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:beans-annotation.xml"); TestObject to = (TestObject)ctx.getBean("testObject"); System.out.println(to); UserController userController = (UserController) ctx.getBean("userController"); System.out.println(userController); // userController.execute(); UserService userService = (UserService) ctx.getBean("userService"); System.out.println(userService); UserRepository userRepository = (UserRepository) ctx.getBean("userRepositoryImpl"); System.out.println(userRepository); } }
com.fafa.spring.bean.annotation.TestObject@b8be647 com.fafa.spring.bean.annotation.service.UserController@dbb453d com.fafa.spring.bean.annotation.controller.UserService@1beaed6 com.fafa.spring.bean.annotation.repository.UserRepositoryImpl@dc8647f
- 如果此时使用
resource-pattern
指定扫描的类,则容器中就只会有指定的扫描的bean<context:component-scan base-package="com.fafa.spring.bean.annotation" resource-pattern="repository/*.class"></context:component-scan>
- 如果要注入的bean可能不存在的时候可以使用
@Autowired(required=false)
指定不是必须的
注释掉TestObject
类中的@Component
,将UserRepositoryImpl
的TestObject
的注解设置为@Autowired(required=false)
测试:
测试结果:testObject为nullpublic static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:beans-annotation.xml"); UserRepository userRepository = (UserRepository) ctx.getBean("userRepositoryImpl"); userRepository.save(); System.out.println(userRepository); }
该方式避免了在使用的bean时候发生bean找不到的错误。UserRepositoryImpl Save... null com.fafa.spring.bean.annotation.repository.UserRepositoryImpl@7af2a691
- 再新建一个
UserJdbcRepositoryImpl.java
实现UserRepository
接口,添加@Repository
注解:@Repository public class UserJdbcRepositoryImpl implements UserRepository { @Override public void save() { System.out.println("UserJdbcRepository save。。。。。"); } }
- 此时在通过
UserRepository
接口调用方法的时候,会报bean不唯一的错:
错误信息:public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:beans-annotation.xml"); UserController userController = (UserController) ctx.getBean("userController"); System.out.println(userController); userController.execute(); } }
要解决这个问题,可以使用No qualifying bean of type [com.fafa.spring.bean.annotation.repository.UserRepository] is defined: expected single matching bean but found 2: userJdbcRepositoryImpl,userRepositoryImpl
@Qualifier
注解指定调用接口对应的bean名称,如UserSerive
中:
使用@Service public class UserService { private UserRepository userRepository; @Autowired public void setUserRepository(@Qualifier("userJdbcRepositoryImpl") UserRepository userRepository) { this.userRepository = userRepository; } public void add(){ System.out.println("UserService add..."); userRepository.save(); } }
@Qualifier("userJdbcRepositoryImpl")
标注使用UserJdbcRepositoryImpl
类中的方法:com.fafa.spring.bean.annotation.service.UserController@7dcf7147 UserController execute... UserService add... UserJdbcRepository save。。。。。
- 此外还可以使用
context:exclude-filter
和context:include-filter
来指定在包扫描时要包含的包或要排除的包,以及使用use-default-filters="false"
来指定只扫描指定的组件<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"> <!-- 指定SpringIOC容器扫描的包 --> <!-- 可以通过resource-pattern指定扫描的资源 --> <!-- <context:component-scan base-package="com.fafa.spring.bean.annotation" resource-pattern="repository/*.class"></context:component-scan> --> <!-- context:exclude-filter 子节点指定排除哪些指定表达式的组件 --> <!-- context:include-filter 子节点指定包含哪些指定表达式的组件,该子节点需要use-default-filters 配合使用 use-default-filters: 默认的filter是会全部扫描组件的,设为false后就只会使用指定的组件 --> <context:component-scan base-package="com.fafa.spring.bean.annotation"> <!-- use-default-filters="false" --> <!-- <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/> <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/> --> <context:exclude-filter type="assignable" expression="com.fafa.spring.bean.annotation.repository.UserJdbcRepositoryImpl"/> <!-- <context:include-filter type="assignable" expression="com.fafa.spring.bean.annotation.repository.UserRepositoryImpl"/> --> </context:component-scan> </beans>