JavaConfig+springboot入门

JavaConfig出现历史

Spring1.x 时代

通过xml文件配置bean,随着项目的不断扩大,需要将xml配置分放到不同的配置文件中,需要频繁的在java类和xml配置文件中切换;但是,Spring的依赖注入与声明式事务意味着组件之间再也不存在紧耦合,再也不用重量级的EJB了。

Spring2.x 时代

随着JDK 1.5带来的注解支持,Spring2.x可以使用注解对Bean进行申明和注入,大大的减少了xml配置文件,同时也大大简化了项目的开发。
注解与xml共存:
应用的基本配置用xml,比如:数据源、资源文件等;
业务开发用注解,比如:Service中注入bean等;

@Contrller @Service 等 @Autowired

Spring3.x -Spring4.x

从Spring3.x开始提供了Java配置方式,使用Java配置方式可以更好的理解你配置的Bean,现在我们就处于这个时代,并且Spring4.x和Spring boot都推荐使用java配置的方式。
如@Configuration 和 @Bean的出现
Spring的Java配置方式是通过 @Configuration 和 @Bean 这两个注解实现的:
@Configuration 作用于类上,相当于一个xml配置文件;
@Bean 作用于方法上,相当于xml配置中的;
至此注解慢慢的取代了xml配置。

Spring5.x

Spring 5.0 GA版本于2017年9月28日发布。Spring 5.0开始支持JDK 8和Java EE 7,同时兼容JDK9。全面支持Servlet 3.1,还引入了一个全新的模块Spring WebFlux用于替代老话的 spring-webmvc;对Kotlin也有了更好的支持。

spring核心

环境搭建

<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.3.12.RELEASE</version>
		</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>4.3.12.RELEASE</version>
</dependency>

Spring测试

方式1-new容器

public class IOCTest {

    // 1 基于xml配置文件
    @Test
    public void test()throws Exception{

        //通过xml初始化spring容器
        ApplicationContext context = new
                ClassPathXmlApplicationContext("beans.xml");
        System.out.println(context.getBean(Date.class));

        //向获取spring中所有的bean的类型
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }

    }
}

方式2-测试创建容器

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTestTest {

    @Autowired
    private ApplicationContext applicationContext;
 
@Test
public void test2() throws Exception{

    System.out.println(applicationContext);
    String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
    for (String beanDefinitionName : beanDefinitionNames) {
        System.out.println(beanDefinitionName);
    }
}

Ioc-xml

Classpathxml*applictionContext

<?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: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
      ">
    <bean id="myDate" class="java.util.Date">
  scope="singleton" lazy-init="true" init-method="" destroy-method="" >
        <property name="name" value="zs"></property>
        <property name="otherBean" ref=""

</bean>
</beans>

Ioc-注解

扫描注解

<?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:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-2.5.xsd
">

    <context:component-scan base-package="cn.itsource._03iocanno_">

    </context:component-scan>
</beans>


配置注解
package cn.itsource._03iocanno_;

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

//controller service repository componet
@Component
public class MyBean {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Autowired
    private OtherBean otherBean;

    public OtherBean getOtherBean() {
        return otherBean;
    }

    public void setOtherBean(OtherBean otherBean) {
        this.otherBean = otherBean;
    }
}

Spring javaconfig-IOC

组件注册

1.创建项目并且导入pom

创建maven并导入一下内容:

<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.3.12.RELEASE</version>
		</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>4.3.12.RELEASE</version>
</dependency>

2.配置类&Bean注解&测试

@Configuration:加了这个注解的类就相当于传统的一个applicationContext-xxx.xml
@Bean:在标注了@Configuration的类里面的方式上面打上@bean就相当于在applicationContext-xxx.xml配置的一个
Dao的名字默认就是方法名,如果想改方法名使用@Bean(“beanName”)

package cn.itsource._04iocjavaconfig_;

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

@Configuration //相当于原来的applicationContext-x.xml
public class IocConfig {

    /**
     * <bean id="myBean" class="cn.itsource._04iocjavaconfig_.MyBean"></bean>
     * @return
     */
    @Bean
    public MyBean myBean(){
        return new MyBean();
    }
}

package cn.itsource._04iocjavaconfig_;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * javaconfig配置bean其实就是以配置类(@Configration)代替xml配置,通过@Bean的方式配置bean
 * 获取容器
 *    new的方式: new AnnotationConfigApplicationContext(IocConfig.class);
 *    spring 测试的方式: @ContextConfiguration(classes = IocConfig.class)
 */
    //方式2: springtest
    @RunWith(SpringJUnit4ClassRunner.class)
//不用xml,直接指定配置类
    @ContextConfiguration(classes = IocConfig.class)
    public class SpringTestTest {

    @Autowired
    private ApplicationContext applicationContext;
    //junit测试 AnnotationConfigApplicationContext注解方式,需要传入配置类
    @Test
    public void test1() throws Exception{
        //spring测试-从容器中获取bean- 获取容器(ApplicatitonContext)
        // 1 直接new 配置类就相当于原来spring配置文件
        ApplicationContext context =
                new AnnotationConfigApplicationContext(IocConfig.class);

        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
    }

    @Test
    public void test2() throws Exception{

        System.out.println(applicationContext);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
    }
}

3.@ComponentScan扫描bean

我们原来使用spring的使用不会在xml中一个一个配置bean,我们在再类上加上@Repository,@Service,@Controller @Component,并且注入时可以使用@AutoWired的注解注入。 这一切的功能都需要我们配置包扫描<context:component-scan base-package=“cn.itsource”/>.
然而现在注解驱动开发已经没有了配置文件,不能配置。但是提供了@ComponentScan,我们可以在配置类上面加上这个注解也是一样,并且也能扫描配置包项目的相关注解,也能完成自动注入。

a.基本语法

配置类:

//注解类==配置文件
@Configuration //告诉spring这是一个注解类
@ComponentScan("cn.itsource")
public class MainConfig {

    //相当于在xml中配置了<bean id="" class="cn.itsource.dao.UserDao"><bean/>
    @Bean("userDao") //指定bean的名字
    public UserDao userDao01(){
        return new UserDao();
    }
}

Dao:不变还使用Bean方式
Service:

@Service
public class UserService {
public User getUser(Long id){
      System.out.println("userservice...");       
 return null;
    }
}
Controller:
@Controller
public class UserController {
    //先不拷贝页面,直接打印即可
    public  User getUser(Long id){
        System.out.println("usercontroller...");       
 return null;

    }
}

测试:

       ApplicationContext context = new AnnotationConfigApplicationContext
                (MainConfig.class);
        for (String beanName : context.getBeanDefinitionNames()) {
            System.out.println(beanName);
        }

b.高级语法

//注解类==配置文件
@Configuration //告诉spring这是一个注解类
//多个扫描配置方法1:配置多个ComponentScan
//@ComponentScan(value = "cn.itsource")
//@ComponentScan(value = "cn.itsource")
    //includeFilters = Filter[] 包含过滤器
    //excludeFilters = Filter[] 排除过滤器
    //useDefaultFilters = 使用默认过滤器
//多个扫描配置方法2:使用ComponentScans
@ComponentScans(value = {
        @ComponentScan(
                value = "cn.itsource"
//                ,excludeFilters = { //排除 //excludeFilters = Filter[] 排除过滤器
//                        @ComponentScan.Filter(type = FilterType.ANNOTATION
//                                ,classes = {Controller.class})
//                }
                ,includeFilters = {//includeFilters = Filter[] 包含过滤器
                @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {
                        Controller.class
                })
        }
                ,useDefaultFilters = false //关闭默认全部扫描includeFilters才能生效
        )
})

public class MainConfig {

    //相当于在xml中配置了<bean id="" class="cn.itsource.dao.UserDao"><bean/>
    @Bean("userDao") //指定bean的名字
    public UserDao userDao01(){
        return new UserDao();
    }
}

注意1分开测试排除和包含
注意2:其他配置类影响-本身扫描也包含配置类

4.Bean详情-@Scope 组件范围&@Lazy 懒加载-认识

设置bean的名称
1)@Scope单例测试
JavaConfig+springboot入门
2)@Lazy懒加载
JavaConfig+springboot入门

5.Bean详情-注入

1 new 不在容器中
2 在容器中,调用方法 ok
3 @AutoWare,注入再设置
4 构造函数注入-推荐

public MyBean xxx(){
        // 方式1:创建对象直接设置值,没有在spring中,不较注入
//        OtherBean otherBean = new OtherBean();
//        MyBean myBean = new MyBean();
//        myBean.setOtherBean(otherBean);
        // 方式2:直接调用方法
//        MyBean myBean = new MyBean();
//        // 智能发现如果已经通过该方法注册了bean,直接注入就ok,不会再新创建一个了。
//        myBean.setOtherBean(otherBean());

        //方式3:对注入的bean进行设置值
        MyBean myBean = new MyBean();
        myBean.setOtherBean(otherBean);
        return myBean;
    }


    //方式4 通过构造函数进行注入 推荐使用
    @Bean
    public MyBean yyy(OtherBean otherBean){
        return new MyBean(otherBean);
    }
    @Bean
    public OtherBean otherBean(){
        return new OtherBean();
    }

6.@Conditional-按照条件注册

@Conditional(value = LinuxCondition.class) //放到类上面下面所有方法都生效,但是如果方法上加了优先级更高
public class MainConfig1 {

    //相当于在xml中配置了<bean id="" class="cn.itsource.dao.UserDao"><bean/>
    @Bean("userDao") //指定bean的名字
    //@Scope(value = "protoType") //默认值为为单实例,默认值为是创建容器时就创建对象
    @Lazy //只对单实例有用,表示创建容器时不创建对象,只有第一次使用时创建对象
    public UserDao userDao01(){
        return new UserDao();
    }

    @Bean
    public UserDao userDaoLinux(){
        return new UserDao();
    }
    //可以加到方法上面,也可以加到类上面. 根据当前os.name的环境来判断
    @Bean
    @Conditional(value = WindowsCondition.class)
    public UserDao userDaoWindows(){
        return new UserDao();
    }
}

/**
 * @author yaohuaipeng
 * @date 2019/7/15-12:11
 */
public class WindowsCondition 
        implements Condition {
    /**
     *
     * @param context conditionContext条件上下文,可以获取一些信息,来判断是否条件
     * @param annotatedTypeMetadata 当前方法或注解类的注解类型元数据信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata annotatedTypeMetadata) {

        //常用方法
        //1 获取beanFactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //2 获取类家长群
        ClassLoader classLoader = context.getClassLoader();
        //3 获取当前运行环境
        Environment environment = context.getEnvironment();
        //4 获取bean的注册器,获取手动注册bean到spring容器
        BeanDefinitionRegistry registry = context.getRegistry();
        String osName = environment.getProperty("os.name");
        if (osName.contains("Windows")){
            return  true;
        }

        return false;
    }
}
测试:
/**
    *  按照条件进行注册
    */
    @Test
    public void testCondition ()
    {

        ApplicationContext context = new AnnotationConfigApplicationContext
                (MainConfig.class);
        System.out.println(context.getEnvironment().getProperty("os.name"));
        String[] beanNames = context.getBeanNamesForType(UserDao.class);
        for (String beanName : beanNames) {
            System.out.println(beanName);
        }

    }

7.@Import

//注解类==配置文件
@Configuration //告诉spring这是一个注解类
@Import({RedColor.class, GreenColor.class, MyImportSelector.class, My r.class})
public class MainConfig {
}
 /**
    * 创建bean的方式
     * 方式1:@ComponentScan+注解(@Controller+@Service+@Repository+@Compont)-自己创建的bean
     * 方式2:@Bean 别人的bean
     * 方式3:@Import(快速向容器中注册一个bean)
     *      1)@Import(要导入的组件),名称就是累的全限定名
     *      2)ImportSelector:导入选择器,返回需要导入组件类的全限定名数组-springboot底层用的多
     *      3)ImportBeanDefinitionRegistrar:通过bean定义注册器手动项目spring中容器中注册
     * 方式4:FactoryBean的方式,返回的是getObject的类实例-和其他框架集成是用的多
    */
    @Test
    public void testImport ()
    {
        ApplicationContext context = new AnnotationConfigApplicationContext
                (MainConfig.class);
        String[] beanNames = context.getBeanDefinitionNames();
        for (String beanName : beanNames) {
            System.out.println(beanName);
        }

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

/**
 * @author yaohuaipeng
 * @date 2019/7/15-14:18
 */
public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        //所打注解类上面所有的信息都能获取到
        return new String[]{"cn.itsource.importtest.BlueColor",
                "cn.itsource.importtest.YellowColor"};
    }
}
package cn.itsource.importtest;

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;

/**
 * @author yaohuaipeng
 * @date 2019/7/15-14:23
 */
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    /**
     *
     * @param annotationMetadata 注解上下文
     * @param beanDefinitionRegistry 注册器
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata,
                                        BeanDefinitionRegistry beanDefinitionRegistry) {

        /**
         * XxxColor:beanName
         * bean的定义:
         *    RootBeanDefinition 表示没有层级关系之间注册到根上面
         */
        beanDefinitionRegistry.registerBeanDefinition("XxxColor",
                new RootBeanDefinition(XxxColor.class));
    }
}

8.使用FactoryBean注册组件

//注解类==配置文件
@Configuration //告诉spring这是一个注解类
@Import({RedColor.class, GreenColor.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig {

    @Bean
    public PersonFactoryBean personFactoryBean(){
        return new PersonFactoryBean();
    }
}


/**
 * @author yaohuaipeng
 * @date 2019/7/15-14:30
 */
public class PersonFactoryBean implements FactoryBean<Person> {
    @Override
    public Person getObject() throws Exception {
        return new Person();
    }

    @Override
    public Class<?> getObjectType() {
        return Person.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}


  @Test
    public void testFactoryBean ()
    {
        ApplicationContext context = new AnnotationConfigApplicationContext
                (MainConfig.class);
        //cn.itsource.factorybean.Person@69b794e2 不是返回factoryBean,而是里面的内容
        Object person = context.getBean("personFactoryBean");
        System.out.println(person);
        Object person1 = context.getBean("&personFactoryBean");
        System.out.println(person1.getClass());

        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
    }

组件生命周期

Bean生命周期:创建----初始化----销毁
我们可以自定义bean的初始化和销毁方法,并进行指定,bean在容器进行到对应生命周期时就会调用对应的方案. xml配置方式
1.创建
单实例bean:在容器创建是就进行指定
多实例bean:在每次使用时创建
2.初始化
容器创建完成,并赋值好,完成初始化
3.销毁
单实例bean:容器关闭时进行销毁
多实例bean:没有受spring管理,具体什么时候销毁有用户决定。

Spring Boot

它的出现解决了传统spring项目以下的问题:
1.配置负责繁多
每一个组件集成spring都需要编写对应配置文件,比如appplicationContext-xxx.xml
2.混乱的依赖管理
在spirng中想集成对应组件时,需要导入N多的pom,并且还有考虑版本。
我们使用SpringBoot创建java应用,只需填写很少配置和依赖就能快速搭建,并使用java –jar 启动它,就能得到一个生产级别的web工程。非常方便

Spring Boot特点

Spring Boot 主要目标是:

  • 为所有 Spring 的开发者提供一个非常快速的、广泛接受的入门体验
  • 开箱即用(启动器starter-其实就是SpringBoot提供的一个jar包),但通过自己设置参数(.properties),即可快速摆脱这种方式。
  • 提供了一些大型项目中常见的非功能性特性,如内嵌服务器、安全、指标,健康检测、外部化配置等
  • 绝对没有代码生成,也无需 XML 配置。

Spring boot入门

1.搭建项目

a.创建springboot_01_helllo 项目

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.5.RELEASE</version>
  </parent>
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
</dependencies>

b.码测试

1)新建启动类(App – Main方法)
JavaConfig+springboot入门
2)新建一个Controller类

JavaConfig+springboot入门
3)测试代码
运行:App
浏览器:http://localhost:8080/hello

JavaConfig+springboot入门JavaConfig+springboot入门 早春一去又如何 发布了11 篇原创文章 · 获赞 5 · 访问量 83 私信 关注
上一篇:使用 JavaConfig 的好处


下一篇:软件开发中模块的内聚