Spring---IOC/DI(二)

Spring--bean装配(二)

多环境测试

使用H2内嵌数据库+Pure Spring测试

数据准备

# schema.sql
create table bean_test(
id int identity,
name varchar(255)
);

# data.sql
insert into  bean_test (id,name) values (1,'user-1');
insert into  bean_test (id,name) values (2,'user-2');

实体

package com.spring.study.profile.condition.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
}

package com.spring.study.profile.condition.bean;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;

import javax.sql.DataSource;

@Configuration
public class DataSourceConfig {
    @Bean(destroyMethod = "shutdown")
    @Profile("dev")
    public DataSource embeddedDataSource(){
        return new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.H2)
                .addScript("classpath:schema.sql")
                .addScript("classpath:data.sql")
                .build();
    }
}

JDBC测试

package com.spring.study.bean.profile.condition.bean;

import com.spring.study.profile.condition.bean.DataSourceConfig;
import com.spring.study.profile.condition.bean.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = DataSourceConfig.class)
@ActiveProfiles("dev")
@Slf4j
public class DatasourceTest {
    @Autowired
    private DataSource dataSource;

    private static final String SELECT_SQL = "select * from bean_test";
    @Test
    public void getAll(){
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            conn = dataSource.getConnection();
            stmt = conn.prepareStatement(SELECT_SQL);
            rs = stmt.executeQuery();
            User user = null;
            while (rs.next()){
                user = new User();
                user.setId(rs.getInt(1));
                user.setName(rs.getString(2));
                log.info(user.toString());
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if (rs != null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if (stmt != null){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if (conn != null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

XML配置形式 + 引入JdbcTemplate简化查询操作

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">
<!--        激活相同id的bean @ActiveProfiles-->
<!--        spring.profiles.active/spring.proflies.default-->
<!--        DispatcherServlet; <context-param>-->
    <context:component-scan base-package="com.spring.study.profile.condition.bean"/>
    <beans profile="dev">
        <jdbc:embedded-database id="dataSource" type="H2">
            <jdbc:script location="schema.sql"/>
            <jdbc:script location="data.sql"/>
        </jdbc:embedded-database>
    </beans>

</beans>
package com.spring.study.bean.profile.condition.bean;

import com.spring.study.profile.condition.bean.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:profile-config.xml")
@ActiveProfiles("dev")
@Slf4j
public class DataSourceTestWithXml {
    @Autowired
    private DataSource dataSource;
    private JdbcTemplate jdbcTemplate;

    @Autowired
    public void setJdbcTemplate() {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    private static final String SELECT_SQL = "select * from bean_test where id = ?";

    @Test
    public void testGetOne(){
        User user = jdbcTemplate.queryForObject(SELECT_SQL,new UserRowMapper(),1);
        log.info(user.toString());
    }

    private static final class UserRowMapper implements RowMapper<User>{
        @Override
        public User mapRow(ResultSet rs, int rowNum) throws SQLException {
            return new User(
            rs.getInt(1),
            rs.getString(2)
            );
        }
    }
}

Condition条件化配置bean

package com.spring.study.profile.condition.bean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;

@Configuration
@PropertySource("classpath:params.properties")
public class ConditionBean {
    @Autowired
    Environment environment;
    @Bean
    @Conditional(CheackBean.class)
    public MyBean myBean(){
        MyBean myBean = new MyBean();
        myBean.setName(environment.getProperty("user.name"));
        return myBean;
    }
}

package com.spring.study.profile.condition.bean;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class CheackBean implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Environment environment = conditionContext.getEnvironment();
        return environment.containsProperty("user.name");
    }
}

package com.spring.study.bean.profile.condition.bean;

import com.spring.study.profile.condition.bean.ConditionBean;
import com.spring.study.profile.condition.bean.MyBean;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ConditionBean.class)
public class MyBeanTest {
    @Autowired
    private MyBean myBean;
    @Test
    public void testNotNull(){
        Assert.assertNotNull(myBean);
    }
}

ConditionContext接口简述

image.png

getRegistry() 检查bean的定义
getBeanFactory() 检查bean是否存在
getEnvironment() 检查环境变量是否存在
getResourceLoader 返回ResourceLoader加载的所有资源
getClassLoader 加载并检查类是否存在

image.png

profile原理

package org.springframework.context.annotation;

import java.util.Iterator;
import java.util.List;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.MultiValueMap;

class ProfileCondition implements Condition {
    ProfileCondition() {
    }

    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //当前环境变量不为null则取出所有属性
        if (context.getEnvironment() != null) {
            MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
            if (attrs != null) {
                Iterator var4 = ((List)attrs.get("value")).iterator();

                Object value;
                do {
                    if (!var4.hasNext()) {
                        //不匹配
                        return false;
                    }

                    value = var4.next();
                } while(!context.getEnvironment().acceptsProfiles((String[])((String[])value)));

                return true;
            }
        }
        //默认创建
        return true;
    }
}

posted @ 2020-07-21 03:47  Dave-Mo  阅读(86)  评论(0)    收藏  举报