IOC 入门案例
引入依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
</dependencies>
创建接口及其配置类
public interface AccountService {
void saveAccount();
}
@Service("accountService") // 把当前类对象存入Spring容器中
public class AccountServiceImpl implements AccountService {
@Override
public void saveAccount() {
System.out.println("调用了 AccountServiceImpl 的 save 方法");
}
}
配置类及其测试方法
import com.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration // 指定当前类是一个配置类
// 通过注解指定spring在创建容器时要扫描的包
// basePackages的作用是一样的。我们使用此注解就等同在 xml中配置了 <context:component-scan base-package=“com”/>
@ComponentScan(basePackages = "com")
public class ApplicationTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationTest.class);
AccountService accountService = applicationContext.getBean("accountService", AccountService.class);
accountService.saveAccount();
}
}
测试结果
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O6DLT8AD-1587956051378)(F:\笔记\Spring\image\入门案例测试.png)]](https://i-blog.csdnimg.cn/blog_migrate/80d5a00535e732ec73979ac0813657ea.png)
创建 bean 的注解
测试所需要的两个实例对象
public class Woman {
private String name;
private int age;
// 需要的构造方法 Getter / Setter toString() 自行补充
}
import java.util.Date;
public class Person {
private String name;
private int age;
// 需要的构造方法 Getter / Setter toString() 自行补充
}
| 注解 | 作用 |
|---|---|
@Component | 把当前类对象存入 Spring 容器中 |
@Controller | 把当前类对象存入 Spring 容器中,一般用于表现层 |
@Service | 把当前类对象存入 Spring 容器中,一般用在业务层 |
@Repository | 把当前类对象存入 Spring 容器中,一般用在持久层 |
@Bean | 把当前方法的返回值作为 bean 对象存入 Spring 容器中 |
@import | 允许导入 @Configuration类, ImportSelector 和 ImportBeanDefinitionRegistrar的具体实现, 以及常规组件类 |
方式一:使用 @Component @Controller @Service @Repository
// 说明:这个四个注解的使用方式有一样,使用在类上,表示将当前类对象存入 Spring 容器中,相当于 XML 配置中的 <bean id="" class="">
// 这个注解有一个属性 value ,用于指定 bean 的 id,若不写默认值是当前类名且首字母小写
@Service("accountService") // 把当前类对象存入Spring容器中,并且 bean 的id名为 accountService
public class AccountServiceImpl implements AccountService {
@Override
public void saveAccount() {
System.out.println("调用了 AccountServiceImpl 的 save 方法");
}
}
方式二:使用 @Bean
情况一:@Bean 在配置类中使用
//问题一:什么是配置类
// ① 配置是有注解 @Configuration
// ② 若 ① 不存在,那么就看AnnotationConfigApplicationContext 中的参数是哪个类
//细节点:
//使用 @Bean 配置方法时,如果方法有参数,Spring 框架会容器中查找有没有可用的 bean 对象,查找的方式和Autowired注解是一样的
@Configuration
@ComponentScan(basePackages = "com")
public class ApplicationTest {
@Bean
public Woman getWoman(){
return new Woman("香香",22);
}
@Bean
public Person getPerson(){
return new Person("李四",15);
}
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationTest.class);
// 测试 @Bean
Person person = (Person) applicationContext.getBean("getPerson");
System.out.println(person);
}
}
测试结果:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ezlwkkJ-1587956051380)(F:\笔记\Spring\image@Bean参数自动注入.png)]](https://i-blog.csdnimg.cn/blog_migrate/dda2dca47efacb6a33a33d69ab39faf1.png)
情况二:@Bean 没有在配置类中使用
import com.domain.Person;
import org.springframework.context.annotation.Bean;
public class InstanceFactory {
@Bean
public Person getPerson(){
String name = "李四";
int age = 15;
return new Person(name,age);
}
}
@Configuration
@ComponentScan(basePackages = "com")
@Import(InstanceFactory.class) // 使用 @Import 注解将含有 @Bean 注解的类导进来
public class ApplicationTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationTest.class);
// 测试@ Bean
Person person = (Person) applicationContext.getBean("getPerson");
System.out.println(person);
}
}
方式三:使用 @Import 注解
@Configuration
@ComponentScan(basePackages = "com")
@Import(InstanceFactory.class) // 使用了该注解进行导入之后,那么导入的类也会加入到容器中
public class ApplicationTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationTest.class);
// 测试 @Import
InstanceFactory factory = applicationContext.getBean(InstanceFactory.class);
System.out.println(factory); // 输出:com.factory.InstanceFactory@53bd8fca
}
}
方式四:实现 FactoryBean 接口
import com.domain.Woman;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.support.FactoryBeanRegistrySupport;
public class WomanFactoryBean implements FactoryBean<Woman> {
// 返回该FactoryBean“生产”的对象实例,我们需要实现该方法以给出自己的对象实例化逻辑
@Override
public Woman getObject() throws Exception {
return new Woman("Mary",15);
}
// 方法仅返回getObject()方法所返回的对象的类型,如果预先无法确定,则返回null
@Override
public Class<?> getObjectType() {
return Woman.class;
}
}
@Configuration
@ComponentScan(basePackages = "com")
public class ApplicationTest {
@Bean
public WomanFactoryBean womanFactoryBean(){
return new WomanFactoryBean();
}
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationTest.class);
// 实现 FactoryBean 接口
// 默认获取到的是工厂bean调用getObject创建的对象
Object woman1 = applicationContext.getBean("womanFactoryBean");
System.out.println(woman1); // 结果:Woman{name='Mary', age=15}
// 要获取工厂Bean本身,我们需要给id前面加一个&
Object woman2 = applicationContext.getBean("&womanFactoryBean");
System.out.println(woman2); // 结果:com.factory.WomanFactoryBean@1cdc4c27
}
}
方法五:实现 BeanFactoryPostProcessor 接口
import com.domain.Woman;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
@Component // 将当前类加入 Spring 容器中
public class PostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 通过次方法注册 bean 并方法 Spring 容器
beanFactory.registerSingleton("woman",new Woman("李四",15));
}
}
@Configuration
@ComponentScan(basePackages = "com")
public class ApplicationTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationTest.class);
// 测试
Woman woman = applicationContext.getBean("woman",Woman.class);
System.out.println(woman); // 结果:Woman{name='李四', age=15}
}
}
注入数据的注解
| 注解 | 作用 |
|---|---|
@AutoWired | 按照类型自动注入 |
@Qualifier | 在按照类型注入的基础之上再按照名称注入;它在给类成员注入时不能单独使用;但是在给方法参数注入时可以 |
@Resource | 直接按照 bean 的 id 注入,它可以独立使用 |
@Value | 用于注入基本类型和 String 类型的数据 |
@PropertySource | 用于指定 properties 文件的位置 |
**注意点:**前三个注解都只能注入其他 bean 类型的数据。基本类型和 String 类型无法使用上述注解实现。集合类型的注入只能通过 XML来实现
@AutoWired注解的使用:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component // 1. 将该类放在 Spring 容器中
public class Man {
@Autowired // 2. 注解使用在属性上:表示 Spring 容器会自动注入值
private Person person;
// 3. 注解使用在方法上:表示 Spring 容器会在类加载后自动注入这个方法的参数,并执行一遍方法。
@Autowired
public void showPerson(Person person){
System.out.println(person);
}
// 需要的构造方法 Getter / Setter toString() 自行补充
}
import org.springframework.stereotype.Component;
@Component // 将该类放在 Spring 容器中
public class Person {
private String name = "李四";
private int age = 15;
// 需要的构造方法 Getter / Setter toString() 自行补充
}
@Configuration
@ComponentScan(basePackages = "com")
public class ApplicationTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationTest.class);
//测试 @Autowired
Man man = applicationContext.getBean(Man.class);
System.out.println(man);
}
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dh77i6kj-1587956051383)(F:\笔记\Spring\image\AutoWire注解使用.png)]](https://i-blog.csdnimg.cn/blog_migrate/c02feb41bb752497c7e80ba2dac6ef25.png)
@Qualifier注解的使用
@Configuration
@ComponentScan(basePackages = "com")
public class ApplicationTest {
// 向 Spring 容器中加入两个 Person 对象
@Bean(value = "p1")
public Person person1(){
return new Person("李四",22);
}
@Bean(value = "p2")
public Person person2(){
return new Person("李四",23);
}
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationTest.class);
//测试 A
Man man = applicationContext.getBean(Man.class);
System.out.println(man);
}
}
@Component
public class Man {
@Autowired
private Person person;
@Autowired
public void showPerson(Person person){
System.out.println(person);
}
}
由于 @Autowired 是按照类型注入,所以在该案例中,Spring 容器中有两个 Person 对象,则使用 @Autowired 会报错
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZIT7qJb2-1587956051385)(F:\笔记\Spring\image\AutoWire注解报错)]](https://i-blog.csdnimg.cn/blog_migrate/5dde6d8397c045f75aa50d263f938a7d.png)
当容器中有多个需要注入类型得对象时,结合使用 @Qualifier
@Component
public class Man {
// @Qualifier 的 value 属性用于指定注入 bean 的 id
@Autowired
@Qualifier(value = "p1")
private Person person;
@Autowired
@Qualifier(value = "p2")
public void showPerson(Person person){
System.out.println(person);
}
}
@Resource注解的使用
在上述使用 @Autowire 报错得案例中,不仅可以使用 @Autowire 和 @Qualifier组合起来使用,还可以使用 @Resorece 根据 bean 得 id 值进行注入
@Component
public class Man {
// @Resource 的 name属性用于指定 bean 的 id
@Resource(name = "p1")
private Person person;
@Resource(name = "p2")
public void showPerson(Person person){
System.out.println(person);
}
}
@Value 注解的使用
使用方式一:直接注入 String 或基本数据类型
@Component
public class Person {
@Value(value = "李四")
private String name;
@Value(value = "20")
private int age;
}
@Configuration
@ComponentScan(basePackages = "com")
public class ApplicationTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationTest.class);
// 测试 Value
Person person = applicationContext.getBean("person",Person.class);
System.out.println(person);
}
}
测试结果:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nY8mgucx-1587956051388)(F:\笔记\Spring\image\value直接注入.png)]](https://i-blog.csdnimg.cn/blog_migrate/7c05b99271f86c3ad831e3460ac44a14.png)
使用方式二:注入 properties 文件的值
name=张三
age=50
@Component
// 该注解用于指定properties文件的位置
// value属性指定文件的名称和路径关键字
// classpath 表示类路径下
// encoding 表示该文件使用 utf-8 编码,不然结果会出现乱码
@PropertySource(value = "classpath:person.properties",encoding = "utf-8")
public class Person {
@Value(value = "${name}")
private String name;
@Value(value = "${age}")
private int age;
}
@Configuration
@ComponentScan(basePackages = "com")
public class ApplicationTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationTest.class);
// 测试 Value
Person person = applicationContext.getBean("person",Person.class);
System.out.println(person);
}
}
注意点:我在使用 IDEA 的时候加上了 encoding 还是出现了乱码;其解决方案如下:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PqbonE3B-1587956051390)(F:\笔记\Spring\image\处理 @Value的编码问题.png)]](https://i-blog.csdnimg.cn/blog_migrate/a6847ea53dad556a6ba0cf801c8223c2.png)
其他常用注解说明
| 注解 | 说明 |
|---|---|
@Scope | 用于指定 bean 的作用范围;作用和 bean 标签中使用 scope 属性实现的功能是一样的 |
@PreDestroy | 用于指定销毁方法;作用和在 bean 标签中使用 destroy-method 的作用是一样的 |
@PostConstruct | 用于指定初始化方法;作用和在 bean 标签中使用 init-method作用是一样的 |
@Configuration | 指定当前类是一个配置类;配置类作为 AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写 |
@ComponentScan | 用于指定 Spring 在创建容器时要扫描的包; |
有问题可加QQ群一起交流:1076386005
553

被折叠的 条评论
为什么被折叠?



