spring ioc 1

spring ioc其实就是控制翻转,帮你创建对象,不用在自己创建。在需要聚合引入时也会处理对象之间的关系。

ioc其实就是分两步:

第一步:将自己的对象写好后加上能被spring扫描的注解,通常的注解有:@Configuration,@Component,@Service,@Controller等等,看似好多被扫描标识的注解,其实具有被扫描功能的只有@Component,其他注解内部只是包含@Component所有才有了被扫描的功能,因为不会有人喜欢写重复冗余的代码,尤其是工具,所以spring也不会例外。

第二步:扫描的注解是:@ComponentScan,通过指定或默认扫描的范围去扫描标识过的对象,然后创建并加载到ico容器中,可通过ico容器的getBean方法将指定的对象取出使用。

1.ioc容器:org.springframework.context.ApplicationContext,这只是个接口,下面有很多的实现类,也就是说有很多的ico实现容器。我们这里使用的是其中一个叫import org.springframework.context.annotation.AnnotationConfigApplicationContext;的容器做demo演示。

2.扫描注解:@ComponentScan(basePackages = {"com.mr.li.*" }/* , excludeFilters = {@Filter(classes = {Person.class, Animal.class})} */)扫描注解见名知意就是用来扫描需要加载到ico容器中的java类的。可以指明扫描范围,例如填写包名,也可过滤哪些不被扫描 excludeFilters中的内容就是不被扫描的。扫描的注解也较多如:@ComponentScans,@EntityScan,@EnableAsync

上代码:

1:先指定扫描哪些包,包括在里面也创建一些被ioc加载的bean

package com.mr.li.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import com.mr.li.entity.User;

@Configuration
@ComponentScan(basePackages = {
        "com.mr.li.*" }/* , excludeFilters = {@Filter(classes = {Person.class, Animal.class})} */)
public class AppConfig {
    
    @Bean(value = "user1")
    public User getUser() {
        User user = new User();
        user.setId(1000);
        user.setName("旺达");
        return user;
    }
    
    @Bean(value = "user2")
    public User getUser2() {
        User user = new User();
        user.setId(1001);
        user.setName("天天");
        return user;
    }
}

2.创建一些服务接口

package com.mr.li.service;

public interface Person {

    void behavior();
    
}
package com.mr.li.service;

public interface Animal {

    void behavior();
}

3,给这些接口一些实现类

package com.mr.li.service.impl;

import org.springframework.stereotype.Component;

import com.mr.li.service.Animal;

@Component
public class Cat implements Animal {

    @Override
    public void behavior() {
        System.out.println("喵喵喵~~~~~~~~~");
    }

}
package com.mr.li.service.impl;

import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import com.mr.li.service.Animal;

@Primary
@Component
public class Dog implements Animal {

    @Override
    public void behavior() {
        System.out.println("汪汪汪~~~~~~~~~~");
    }

}
package com.mr.li.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import com.mr.li.service.Animal;
import com.mr.li.service.Person;

@Component
public class Man implements Person {

    @Qualifier("cat")
    @Autowired
    private Animal animal;
    
    @Override
    public void behavior() {
        animal.behavior();
    }
}

4.user演示类

package com.mr.li.entity;

import lombok.Data;

@Data
//@Component
public class User {
    
//    @Value(value = "100") //这种直接赋值的优先级最高
    private long id;
    
//    @Value(value = "章大狗")
    private String name;
    
    @Override
    public String toString() {
        return "id:"+ id + "name:" + name;
    }
}

5.测试

package com.mr.li.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.mr.li.config.AppConfig;
import com.mr.li.entity.User;
import com.mr.li.service.Person;
import com.mr.li.service.impl.Man;

import lombok.extern.slf4j.Slf4j;


@Slf4j
public class Test {

    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        Person person = ctx.getBean(Man.class);
        person.behavior();
//        User user = ctx.getBean(User.class);
        User user = ctx.getBean("user2", User.class);
        log.info("user:{}", user);
    }
}

以上代码的行为:

AppConfg:扫描了定义的包,然后在身演示创建一些bean,可以看到同样类型的bean给了不同的名称,这些类对象在扫描后会被加载到ico容器中去,其中在ico中存储的名称就是指定的名称,如果没指定则使用方法名首字母小写作为名称。

Man:人物类,他实现了Person接口,然后自身加了@Component被扫描注解,我们会发现它里面有引入Animal类的,加了@Autowired注解,此注解就是通过ioc引入Animal的实现类对象,但他有2个实现类对象,所以需要指定到底使用哪个实现类作为对象引入。三种方式:

第一种:直接将变量名animal改为他的子类的类名即可,这个类名是ioc中的变量名,默认会将类首字母小写,也可指定。

第二种:在需要引入的实现类上加@Primary注解,此注解意思是如果没有特殊情况就加载他,但在两个实现类上都加也不行,他的优先级小于@Qualifier注解。

第三种:@Qualifier注解,加载引入的类上同@Autowired一起存在,同样需要指定ioc中存储对应的变量名。

Test:演示了,创建一个ioc容器,加载是他内部的事,注意传入加载的第一类即可。然后演示从ioc中取出对象并使用。

上一篇:idea配置注释


下一篇:Hive优化策略