SpringBoot-全注解下的SpringIOC

SpringBoot - 全注解下的SpringIOC

springboot 是基于 springframework的全注解的web框架,它无需配置xml,所以相比较于spring+springmvc它可以节省更多的开发周期

什么是IOC(Inversion of Controller)?

IOC即是控制反转,把创建对象的控制权交给第三方则叫反转。正转则是一般性的j2ee new对象式的开发,多个Bean的容器则叫做IOC容器。反转大大降低了代码的耦合性。

准备 - @Configuration @Bean的简单使用

@Configuration
public class Appconfig{
    @Bean(name="user")
    public User initUser(){
        User user = new User();
        user.setId(1L);
        user.setUserName("user_name_1");
        user.setNote("note_1");
        return user;
    }

}

@Configuration 代表这是一个java配置文件,Spring的容器会根据它来生成IOC容器去装配Bean

@Bean 代表将initUser方法返回的POJO装配到IOC容器中,而其属性name定义这个bean的名称,如果没有配置它,则将方法名称"initUser"作为Bean的名称装配到Spring IOC容器中。

使用实例:

public class IOCTest{
    private static Logger log = Logger.getLogger(IOCTest.class);
    public static void main(String[] args){
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        User user = ctx.getBean(User.class);
        log.info(user.getId());
    }

}

起步 - 如何去装配Bean

1.扫描装配Bean

因为如果用@Bean去一个个装配的话会显得很繁琐,所以推荐使用扫描装配。

@Component:标明哪个类被扫描进入Spring IOC容器。
@ComponentScan:标明采用何种策略去扫描装配Bean。

@Component("user")
public class user{
    @Value("1")
    private Long id;
    @Value("user_name_1")
    private String usename;
    @Value("note_1")
    private String note;
    /**setter and getter**/
}

@Component表示这个类将会被SpringIOC容器扫描装配,其中配置的"user"则是作为Bean的名称。为了让Spring IOC容器装配这个类,需要改造类APPConfig

@Configuration
@ComponentScan
public class Appconfig{
}

这里加入@ComponentScan意味着它会进行扫描,但是它只会扫描类APPConfig所在的当前包和其子包(还可以指定扫描包,看下)。所以也要把User.java移动一下位置。

测试

ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
User user = ctx.getBean(User.class);
log.info(user.getId());

@ComponentScan扫描指定包:

@ComponentScan("com.springboot.demo.*")
@ComponentScan(basePackage={"com.springboot.demo.pojo"})
@ComponentScan(basePackageClasses = {User.class})

Q:当标注了@Service的类在被扫描的包当中,则如何使它不被扫描?
A:还是使用@ComponentScan,不过另加一个参数即可:
@ComponentScan("com.springboot.demo.*",excludeFilters = {@Filter(classes = {Service.class})})

2.装配第三方Bean

当我们需要引入第三包的时候,很可能 希望把第三方包的类对象也放入到SpringIOC的容器中,这是使用@Bean注解就ok了。
举栗(引入DBCP数据源):

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
@Bean(name="dataSource")
public DataSource getDataSource() {
    Properties props = new Properties();
    props.setProperty("driver", "com.mysql.jdbc.Driver");
    props.setProperty("url", "jdbc:mysql://localhost:3306/demo");
    props.setProperty("username", "root");
    props.setProperty("password", "123456");
    DataSource dataSource = null;
    try {
        dataSource = BasicDataSourceFactory.createDataSource(props);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return dataSource;
}

加深 - 依赖注入(Dependency Injection)

依赖注入就是将实例变量传入到一个对象中去。(Dependency injection means giving an object its instance variables)

  • 控制反转是一种思想
  • 依赖注入是一种设计模式

IoC框架使用依赖注入作为实现控制反转的方式,但是控制反转还有其他的实现方式,例如说ServiceLocator,所以不能将控制反转和依赖注入等同。

1. @Autowired

它是Spring中最常用的注解之一,十分重要,它会根据属性的类型(by type)找到对应对的Bean进行注入。
栗子:

//动物接口
public interface Animal {
    public void use();
}
//人类接口
public interface Person {
    //使用动物服务
    public void service();
    //设置动物
    public void setAnimal(Animal animal);
}
public class Dog implements Animal{

    @Override
    public void use() {
        System.out.println("狗【"+Dog.class.getSimpleName()+"】是看门的");
    }
}
public class BussinessPerson implements Person {

    @Autowired
    private Animal animal = null;
    @Override
    public void service() {
        this.animal.use();
    }

    @Override
    public void setAnimal(Animal animal) {
        this.animal = animal;
    }
}

如上,spring容器会通过注解@Autowired将Dog注入到BussinessPerson实例中

Q:但是,加入又有一个动物类cat,那么它会选择哪个注入?怎么解决这个错误?
A: 因为 @Autowired首先会根据类型找到对应的Bean,如果类型不是唯一的,那么它会根据其属性名称和Bean的名称进行匹配。如果匹配得上,就用该Bean,如果还是无法匹配就会抛出异常。

@Autowired
private Animal dog = null;

因为将animal修改为了dog,所以它会找到dog类

注:

  1. 因为@Autowired是一个默认必须要找到对应Bean的注解,所以如果不能确定其标注属性是否存在,或者允许这个被标注的属性为null。则可以配置@Autowired属性required为false。@Autowired(required =false)
  2. 它除了可以标注属性外还可以标注方法。甚至还可以使用在方法参数上
    @Override
    @Autowired
    public void setAnimal(Animal animal) {
        this.animal = animal;
    }

它会使用setAnimal方法从IOC容器中找到对应的动物进行注入。

2. @Primary和@Quelifier

@Primary:它是一个修改优先权的注解,比如上面的例子,当我们有猫有狗时,假设这次使用猫,name只需要在猫类的定义上加入@Primary就可以了

@Component
@Primary
public class Cat implements Animal{
    ......
}

这里的@Primary的含义告诉SpringIOC容器,当发现有多个同类型的Bean时,请优先使用我进行注入.

Q: 如果@Primary作用在多个类上,其结果是IOC容器还是无法区分采用哪个Bean的实例进行注入,那么该采取什么样的情况呢?
A: 可以使用@Quelifier结合@Autowired一起使用,则可以通过类型和名称一起查找Bean。

@Autowired
@Quelifier("dog")
private Animal animal = null;

通过上面的代码,即使cat已经标注了@Primary,但是我们还是可以拿到dog提供服务。

3. 带参数的构造方法实现注入

public class BussinessPerson implements Person {

    private Animal animal = null;
    
    public BussinessPerson(@Autowired @Quelifier("dog") Animal animal){
        this.animal = animal;
    }
    
    @Override
    public void service() {
        this.animal.use();
    }

    @Override
    public void setAnimal(Animal animal) {
        this.animal = animal;
    }
}

上面取消了对animal的@Autowired注解而是在构造参数中加入了@Autowired@Quelifier注解

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,302评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,232评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,337评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,977评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,920评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,194评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,638评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,319评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,455评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,379评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,426评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,106评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,696评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,786评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,996评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,467评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,043评论 2 341

推荐阅读更多精彩内容