4、spring成長之路——springIOC容器(下)

5.spring註解開發(Spring擴展知識)

5.1定義配置類:@Configuration 聲明一個類爲IOC容器 @Bean定義一個Bean

package com.itcloud.annotation;


import com.itcloud.pojo.Student;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CommonConfig {
    @Bean
    public Student student(){
        Student student = new Student();
        student.setId(10l);
        student.setName("configuration");
        return student;
    }
}

測試java

package com.itcloud.pojo.anntation;

import com.itcloud.annotation.CommonConfig;
import com.itcloud.pojo.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AnnotationTest {
    ApplicationContext context = new AnnotationConfigApplicationContext(CommonConfig.class);
    @Test
    public void testAnnotation(){
        Student stu = context.getBean(Student.class);
    }
}

註解@ComponmentScan使用詳解,該註解做用在類上面spring

@ComponentScan(value = "com.itcloud",useDefaultFilters = false,includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {
                Component.class, Service.class, Repository.class
        })
},excludeFilters = {
        @ComponentScan.Filter(type=FilterType.ANNOTATION,classes = {
                Controller.class
        })
})

bean的做用域,@Scope定義在方法上面shell

/**
     * 取值:singleton:默認值,單實例,容器加載的時候進行bean的建立
     *      prototype:容許建立多個對象,使用的時候進行隊形的建立
     */
    @Scope(value = "")

bean的懶加載,@Lazy放在方法上面,在沒有這個註解的時候,bean會在容器啓動的時候進行加載,可是這個註解使用以後,當使用到這個bean的時候纔會進行性bean的加載。數據庫

5.2.按照條件進行注入

@Conditional該註解能夠根據條件進行注入操做,做用類或者方法上面數組

自定義判斷條件:此判斷條件主要的做用是判斷容器中是否存在studentbean,若是存在則注入teacher,不然不注入;app

package com.itcloud.annotation.conditional;

import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class MyConditional implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        BeanDefinitionRegistry registry = context.getRegistry();
        boolean student = registry.containsBeanDefinition("student");
        if(student){
            return true;
        }
        return false;
    }
}
@Bean("teacher")
    @Conditional({MyConditional.class})
    public Teacher teacher(){
        Teacher t = new Teacher();
        t.setId(10l);
        t.setName("李老師");
        return t;
    }

5.3.@Import註解進行注入

具體用法:按照註解的意思咱們能夠導入一個ioc容器,ImportSelector或者ImportBeanDefinitionRegistrar的子類,再或者是一個普通的組件類,即被@Component相關注解修飾的類,那麼普通的類能夠嗎?jvm

/**
     * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
     * or regular component classes to import.
     */

//在這以前咱們自定義了一個Color類ide

@Configuration
@Import({Color.class})
public class CommonConfig {...}

通過測試普通類也是能夠導入的,可是普通類的bean默認的value是全類名:com.itcloud.annotation.vo.Colorpost

ImportSelector測試

自定義一個MyImportSelector.java類實現ImportSelector接口,把須要導入的類經過字符串數組的形式進行返回,必定要是全類名

參數AnnotationMetadata能夠獲取IOC容器上面的註解

package com.itcloud.annotation.myimport;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

public class MyImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.itcloud.annotation.vo.Blue","com.itcloud.annotation.vo.Red"};
    }
}

ImportBeanDefinitionRegistrar測試

package com.itcloud.annotation.myimport;

import com.itcloud.annotation.vo.Yellow;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //這裏能夠進行bean的註冊
        RootBeanDefinition beanDefinition = new RootBeanDefinition(Yellow.class);
        registry.registerBeanDefinition("yellow", beanDefinition);
    }
}

5.四、FactoryBean注入

在2>2.7裏面已經說過了,此處再也不贅述:點擊跳轉

bean的生命週期,在註解中的表現以下:

​ 和xml配置文件類似;

@Bean(value = "student",initMethod = "init",destroyMethod = "destory")

5.五、後置處理詳解

1.註解:@PostConstruct@PreDestory

​ 在這裏必定要將此類注入到容器中,至於怎麼注入,就再也不贅述

package com.itcloud.annotation.vo;

import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;


@Component
public class PostBean {

    public PostBean(){
        System.out.println("構造方法執行.....");
    }

    @PostConstruct
    public void postConstruct(){
        System.out.println("postConstruct......");
    }


    @PreDestroy
    public void destroy(){
        System.out.println("容器關閉以前執行的嗎......");
    }
}

測試結果:

<!--
    構造方法執行.....
    postConstruct......
    ## 容器關閉以前執行以下
    容器關閉以前執行的嗎......
-->

2.兩個接口 InitializingBean DisposableBean

package com.itcloud.annotation.vo;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class PostProcessorBean implements InitializingBean, DisposableBean {


    public PostProcessorBean(){
        System.out.println("PostProcessorBean.....構造方法執行");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("PostProcessorBean.......destroy()");
    }

    //屬性設置完成以後執行,構造方法以後調用
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("PostProcessorBean.......afterPropertiesSet()");
    }
}

3.BeanPostProcessor原理解析

在前面後置處理器中咱們已經瞭解了,經過實現接口BeanPostProcessor能夠進行後置處理,在這裏咱們將要對後置處理原理進行簡單的介紹

​ 定義一個後置處理器

​ 這個處理器會在全部bean建立的時候,構造方法以後執行,全部初始化方法以前執行,而方法postProcessAfterInitialization會在初始化以後調用,不須要容器關閉

package com.itcloud.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class MyProcessor implements BeanPostProcessor{


    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Before*****beanName = " + beanName +"-----bean = " + bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("After*****beanName = " + beanName +"----bean = " + bean);
        return bean;
    }
}
package com.itcloud.processor;


import com.itcloud.annotation.vo.Color;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Component;

@Configuration
@ComponentScan(useDefaultFilters = false, includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {
                Component.class
        })
})
public class ProcessorConfig {

    @Bean
    public Color color(){

        return new Color();
    }
}

源碼解析:

5.六、屬性賦值和自動裝配

1.@Value的使用

package com.itcloud.annotation.vo;


import org.springframework.beans.factory.annotation.Value;

public class Color {

    //直接賦值
    @Value("red")
    private String type;

    //EL表達式
    @Value("#{100.30-13.43}")
    private Double length;

    //引用外部屬性文件

    @Value("${value.username}")
    private String username;

    @Value("${value.password}")
    private String password;
}

在配置類上面必定要引用外部文件,經過註解@PropertySource

package com.itcloud.processor;


import com.itcloud.annotation.vo.Color;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Component;

@Configuration
@ComponentScan(useDefaultFilters = false, includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {
                Component.class
        })
})
@PropertySource("classpath:/properties/value.properties")
public class ProcessorConfig {

    @Bean
    public Color color(){

        return new Color();
    }
}

經過環境變量來獲取屬性的值

Environment environment = context.getEnvironment();
String property = environment.getProperty("value.username");

2.自動裝配使用的註解

2.一、spring註解:@Autowired前面咱們已經說過,這個註解能夠配合@Qualifier使用,明確調用使用特定的Bean

​ @Autowired也能夠配置@Primary註解使用,當類型相同的使用,會優先選擇@Primary註解標識的 bean

2.2.非spring註解:@Resource按照名稱注入,@Inject,@Autowired用法相似,須要引入jar:

<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>

5.6.在類中使用spring底層的組件

若是一個類想要使用spring底層的組件,能夠實現一些接口xxxAware,這個接口都是org.springframework.beans.factory.Aware接口的子類

1.xxxAware方法的使用

package com.itcloud.annotation.vo;


import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.*;
import org.springframework.core.env.Environment;
import org.springframework.util.StringValueResolver;

public class Color implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
    private ApplicationContext context;


    public void userContext(){
        Environment environment = this.context.getEnvironment();
        String property = environment.getProperty("value.url");
        System.out.println(property);

    }


    //獲取applicationContext對象
    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        this.context = context;
    }

    //獲取當前bean的name
    @Override
    public void setBeanName(String name) {
        System.out.println("name===" + name);
    }


    //進行字符串的解析
    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        String result = resolver.resolveStringValue("數據庫的名稱:${value.username}, el表達式解析:#{10-3*3}");
        System.out.println(result);
    }
}
5.6.@Profile的使用

此註解既可使用在bean上,也能夠定義在一個IOC容器上面,激活的方式:

​ 1.類激活

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("development");
ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class);
ctx.refresh();

​ 2.jvm參數激活:

-Dspring.profiles.active="profile1,profile2"
相關文章
相關標籤/搜索