欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring-基于Java类的配置

程序员文章站 2022-07-09 15:22:16
...

概述

JavaConfig是Spring的一个子项目,它旨在通过Java类的方式提供Bean的定义信息,在Spring4.0的版本,JavaConfig正式成为Spring4.0的核心功能。


使用Java类提供Bean定义信息

普通的POJO只要标注了@Configuration注解,就可以为Spring容器提供Bean定义的信息,每个标注了@Bean的类方法都相当于提供一个Bean的定义信息。


实例

代码已托管到Github—> https://github.com/yangshangwei/SpringMaster

Spring-基于Java类的配置

POJO

package com.xgj.ioc.javaConfig;

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

// 将一个POJO标注为定义Bean的配置类
@Configuration
public class Teacher {

    /**
     * 
     * 
     * @Title: studentOne
     * 
     * @Description: 定义了一个Bean,并提供了Bean的实例化逻辑
     * 
     * @return
     * 
     * @return: StudentOne
     */
    @Bean
    public StudentOne studentOne() {
        return new StudentOne();
    }

    /**
     * 
     * 
     * @Title: studentTwo
     * 
     * @Description: 定义了一个Bean,并提供了Bean的实例化逻辑
     * 
     * @return
     * 
     * @return: StudentTwo
     */
    @Bean
    public StudentTwo studentTwo() {
        return new StudentTwo();
    }

    public void arrangeStudent() {
        studentOne().doCleanWork();
        studentTwo().doHomeWork();
    }

}
package com.xgj.ioc.javaConfig;

public class StudentOne {

    public void doCleanWork() {
        System.out.println("StudentOne will do CleanWork");
    }
}
package com.xgj.ioc.javaConfig;

public class StudentTwo {
    public void doHomeWork() {
        System.out.println("StudentTwo will do HomeWork");
    }
}

测试类

package com.xgj.ioc.javaConfig;

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

public class JavaConfigTest {

    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(
                Teacher.class);
        ctx.getBean("teacher", Teacher.class).arrangeStudent();
    }
}

运行结果

Spring-基于Java类的配置


分析

Teacher类的定义出标注了@Configuration注解,说明这个类可以用于为Spring提供Bean的定义信息。
该类的方法可以标注@Bean注解,Bean的类型由方法返回值的类型决定,名称默认和方法名同名,当然也可以通过入参显示指定Bean名称,比如@Bean(name=”coolStudent”).
@Bean所标注的方法体提供了Bean的实例化逻辑。

studentOne()和studentTwo()方法分别定义了一个StudentOne 和 StudentTwo类型的Bean, 他们的Bean名称分别为 studentOne 和 studentTwo。

在arrangeStudent()方法中 注入了上面实例化的两个Bean。

以上配置和下面的xml是等效的

<bean id="studentOne" class="com.xgj.ioc.javaConfig.StudentOne"/>
<bean id="studentTwo" class="com.xgj.ioc.javaConfig.StudentTwo"/>
<bean id="teacher" class="com.xgj.ioc.javaConfig.Teacher"
p:sutdentOne-ref="studentOne" p:studentTwo-ref="studentTwo"/>

基于Java类的配置方式和基于XML或者基于注解的配置方式相比,前者通过代码编程的方式可以更加灵活的实现Bean的实例化及Bean之间的装配,后两者都是通过配置声明的方式,在灵活性上要稍逊一些,但在配置上要更简单一些。


使用基于Java类的配置信息启动Spring容器

1.直接通过@Configuration启动Spring容器

Spring提供了AnnotationConfigApplicationContext类,它能够直接通过标注@Configuration的Java类启动Spring容器。

通过AnnotationConfigApplicationContext的构造函数加载配置类

比如我们上面的那个例子的测试类

package com.xgj.ioc.javaConfig;

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

public class JavaConfigTest {

    public static void main(String[] args) {
        // (1)通过构造函数加载配置类       
        ApplicationContext ctx = new AnnotationConfigApplicationContext(
                Teacher.class);
        ctx.getBean("teacher", Teacher.class).arrangeStudent();
    }
}

在(1)处,通过AnnotationConfigApplicationContext类的构造函数直接传入标注了@Configuration的JAVA类,这届用该类中提供的Bean定义信息启动Spring容器。


通过编码的方式加载多个@Configuration配置类,然后通过刷新容器应用这些配置类

package com.xgj.ioc.javaConfig;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class JavaConfigTest {

    public static void main(String[] args) {
        // 通过构造函数加载配置类
        // ApplicationContext ctx = new AnnotationConfigApplicationContext(
        // Teacher.class);

        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        // 注册@Configuration的配置类,可注册多个
        ctx.register(Teacher.class);
        // 刷新容器以应用这些注册的配置类
        ctx.refresh();

        Teacher teacher = ctx.getBean("teacher", Teacher.class);
        teacher.arrangeStudent();

    }
}

通过@Import将多个配置类组装到一个配置类中,然后仅需注册这个组装好的配置类 ,启动容器

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(DaoConfig.class)
public class ServiceConfig {

    @Autowired
    private DaoConfig daoConfig;

    @Bean
    public LogonService logonService(){
        LogonService logonService = new LogonService();
        System.out.println(daoConfig.logDao() == daoConfig.logDao());
        logonService.setLogDao(daoConfig.logDao());
        logonService.setUserDao(daoConfig.userDao());
        return logonService;
    }
}

AnnotationConfigApplicationContext的主要方法
Spring-基于Java类的配置


2.通过XML配置文件引用@Configuration配置

标注了@Configuration的配置类和标注了@Component的类一样也是一个Bean, 同样的 它也可以被Spring的<context:component-scan>扫描到。 因此如果希望将配置类组装到XML的配置文件中,通过XML的配置文件启动Spring,这仅需要在XML子中通过<context:component-scan>扫描到相应的配置类即可。

我们改造下上面的测试类

Spring-基于Java类的配置

增加配置文件:

<?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">


    <!-- (1)声明Context命名空间以及Schema文件 (2)扫描类包以及应用注解定义的bean  resource-pattern 看需求,可配置可不配置 -->
    <context:component-scan base-package="com.xgj.ioc.javaConfig"
        resource-pattern="Teacher.class" />

</beans>
package com.xgj.ioc.javaConfig;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class JavaConfigTest {

    public static void main(String[] args) {

    ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "classpath:com/xgj/ioc/javaConfig/beans.xml");

        Teacher teacher = ctx.getBean("teacher", Teacher.class);
        teacher.arrangeStudent();

    }
}

同样也可以正确的加载并实例化Bean

2017-07-31 22:03:02,093  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@d167d36: startup date [Mon Jul 31 22:03:02 BOT 2017]; root of context hierarchy
2017-07-31 22:03:02,176  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/ioc/javaConfig/beans.xml]
StudentOne will do CleanWork
StudentTwo will do HomeWork

3.通过@Configuration配置类引用XML配置信息

假设bean中有两个Bean ,如下

<bean id="userDao" class="com.xgj.ioc.javaConfig.UserDao"/>
<bean id="logDao" class="com.xgj.ioc.javaConfig.LogDao"/>

在@Configuration配置类中可以直接通过@ImportResource引入XML的配置那文件,这样就就可以直接通过@Autowired引用xml配置文件中定义的Bean。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

@Configuration
@ImportResource("classpath:com/xgj/ioc/javaConfig/beans.xml")
public class LogonAppConfig {

    @Bean
    @Autowired
    public LogonService logonService(UserDao userDao,LogDao logDao){
        LogonService logonService = new LogonService();
        logonService.setUserDao(userDao);
        logonService.setLogDao(logDao);
        return logonService;        
    }
}

通过@ImportResource引入XML配置文件
通过@Bean定义一个LogonService 的bean
通过@Autowired自动注入userDao和logDao ,这两个Bean是在XML配置文件中定义的。

需要说明的是,@ImportResource引入XML配置文件,不是@Autowired处可成功注入到对应Bean的前提条件。 只要不同形式的Bean定义信息能够加载到Spring容器中,Spring就可以智能的完成Bean之间的装配。

上一篇: 函数的三种角色

下一篇: MODBUS协议