IOC -> 注解

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)]

创建 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类, ImportSelectorImportBeanDefinitionRegistrar的具体实现, 以及常规组件类

方式一:使用 @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)]

情况二:@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直接按照 beanid 注入,它可以独立使用
@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)]


@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注解报错)]

当容器中有多个需要注入类型得对象时,结合使用 @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 根据 beanid 值进行注入

@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)]

使用方式二:注入 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)]

其他常用注解说明
注解说明
@Scope用于指定 bean 的作用范围;作用和 bean 标签中使用 scope 属性实现的功能是一样的
@PreDestroy用于指定销毁方法;作用和在 bean 标签中使用 destroy-method 的作用是一样的
@PostConstruct用于指定初始化方法;作用和在 bean 标签中使用 init-method作用是一样的
@Configuration指定当前类是一个配置类;配置类作为 AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写
@ComponentScan用于指定 Spring 在创建容器时要扫描的包;

有问题可加QQ群一起交流:1076386005

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值