[Spring MVC] @Configuration 的用法

原文出處:https://www.cnblogs.com/duanxz/p/7493276.html

從Spring3.0,@Configuration用於定義配置類,可替換xml配置文件,被註解的類內部包含有一個或多個被@Bean註解的方法,這些方法將會被AnnotationConfigApplicationContextAnnotationConfigWebApplicationContext類進行掃描,並用於構建bean定義,初始化Spring容器。

注意:@Configuration註解的配置類有如下要求:

@Configuration不可以是final類型;
@Configuration不可以是匿名類;
嵌套的configuration必須是靜態類。
一、用@Configuration加載spring
1.1、@Configuration配置spring並啓動spring容器
1.2、@Configuration啓動容器+@Bean註冊Bean
1.3、@Configuration啓動容器+@Component註冊Bean
1.4、使用 AnnotationConfigApplicationContext 註冊 AppContext 類的兩種方法
1.5、配置Web應用程序(web.xml中配置AnnotationConfigApplicationContext)

二、組合多個配置類
2.1、在@configuration中引入spring的xml配置文件
2.2、在@configuration中引入其它註解配置
2.3、@configuration嵌套(嵌套的Configuration必須是靜態類)
三、@EnableXXX註解
四、@Profile邏輯組配置
五、使用外部變量

@Configuation加載Spring方法

@Configuation註解一個類配置應用上下文

@Configuation註解一個類,這個類相當於Spring容器的應用上下文(xml)
配置類

package test;

import org.springframework.context.annotation.Configuration;

@Configuration
public class BeansContainer {
    public BeansContainer(){
        System.out.println("啓動spring容器");
    }
    
}

相當於,這個xml應用上下文

<?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" xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd" default-lazy-init="false">


</beans>

測試

package test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

public class test {
    public static void main(String[] args){
        AbstractApplicationContext context
                = new AnnotationConfigApplicationContext(BeansContainer.class);
    }
}

結果
在這裏插入圖片描述

@Configuration啓動容器+@Bean註冊Bean,@Bean下管理bean的生命週期

@Bean標註在方法上(返回某個實例的方法),等價於spring的xml配置文件中的,作用爲:註冊bean對象

bean類:

package test;

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


@Configuration
public class BeansContainer {
    public BeansContainer(){
        System.out.println("啓動spring容器");
    }

    @Bean("person")
    @Scope("prototype")
    public Person createPerson(){
        return new Person();
    }

    
}

配置類

package test;

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


@Configuration
public class BeansContainer {
    public BeansContainer(){
        System.out.println("啓動spring容器");
    }

    @Bean("person")
    @Scope("prototype")
    public Person createPerson(){
        return new Person();
    }

    
}

測試

package test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

public class test {
    public static void main(String[] args){
        AbstractApplicationContext context
                = new AnnotationConfigApplicationContext(BeansContainer.class);

        Person person = context.getBean("person",Person.class);
    }
}

結果
在這裏插入圖片描述
注:
(1)、@Bean註解在返回實例的方法上,如果未通過@Bean指定bean的名稱,則默認與標註的方法名相同;
(2)、@Bean註解默認作用域爲單例singleton作用域,可通過@Scope(“prototype”)設置爲原型作用域;
(3)、既然@Bean的作用是註冊bean對象,那麼完全可以使用@Component、@Controller、@Service、@Ripository等註解註冊bean當然需要配置@ComponentScan註解進行自動掃描。

@Bean下管理bean的生命週期

可以使用基於 Java 的配置來管理 bean 的生命週期。@Bean 支持兩種屬性,即 initMethoddestroyMethod,這些屬性可用於定義生命週期方法。在實例化 bean 或即將銷燬它時,容器便可調用生命週期方法。生命週期方法也稱爲回調方法,因爲它將由容器調用。使用 @Bean 註釋註冊的 bean 也支持 JSR-250 規定的標準 @PostConstruct@PreDestroy 註釋。如果您正在使用 XML 方法來定義 bean,那麼就應該使用 bean 元素來定義生命週期回調方法。以下代碼顯示了在 XML 配置中通常使用 bean 元素定義回調的方法。

bean類

package test;

public class Person {
    private String name;
    public Person(){
        System.out.println("創建Person對象");
        System.out.println(this);
    }

    public String getName() {
        return name;
    }

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

    public void init(){
        System.out.println("this is init()");
    }
    
    public void destroy(){
        System.out.println("this is destroy");
    }
    
}

配置類

package test;

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


@Configuration
public class BeansContainer {
    public BeansContainer(){
        System.out.println("啓動spring容器");
    }

    @Bean(name = "person",initMethod = "init",destroyMethod = "destroy")
    @Scope("prototype")
    public Person createPerson(){
        return new Person();
    }

    
}

測試

package test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

public class test {
    public static void main(String[] args){
        AbstractApplicationContext context
                = new AnnotationConfigApplicationContext(BeansContainer.class);

        Person person = context.getBean("person",Person.class);

        Person person2 = context.getBean("person",Person.class);


    }
}

結果
在這裏插入圖片描述
分析:

結果中的1:表明initMethod生效

結果中的2:表明@Scope("prototype")生效

@Configuration啓動容器+@Component註冊Bean

bean類:

package test;

import org.springframework.stereotype.Component;

@Component("p")
public class Person {
    private String name;
    public Person(){
        System.out.println("創建Person對象");
        System.out.println(this);
    }

    public String getName() {
        return name;
    }

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

    public void init(){
        System.out.println("this is init()");
    }
    
    public void destroy(){
        System.out.println("this is destroy");
    }
    
}

配置類

package test;

import org.springframework.context.annotation.*;


@Configuration
@ComponentScan(basePackages = "test")
public class BeansContainer {
    public BeansContainer(){
        System.out.println("啓動spring容器");
    }

    /**
    @Bean(name = "person",initMethod = "init",destroyMethod = "destroy")
    @Scope("prototype")
    public Person createPerson(){
        return new Person();
    }*/

    
}

測試

package test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

public class test {
    public static void main(String[] args){
        AbstractApplicationContext context
                = new AnnotationConfigApplicationContext(BeansContainer.class);

        Person person = context.getBean("p",Person.class);

    }
}

@Component("beanName")指定bean的名字,便於取用bean

使用 AnnotationConfigApplicationContext 註冊 AppContext 類的兩種方法

配置類的註冊方式是將其傳遞給 AnnotationConfigApplicationContext 構造函數

	// @Configuration註解的spring容器加載方式,用AnnotationConfigApplicationContext替換ClassPathXmlApplicationContext
    ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);

	//獲取bean
	TestBean tb = (TestBean) context.getBean("testBean");
	tb.sayHello();

AnnotationConfigApplicationContext 的register 方法傳入配置類來註冊配置類

public static void main(String[] args) {
  ApplicationContext ctx = new AnnotationConfigApplicationContext();
  ctx.register(AppContext.class)
}
配置Web應用程序(web.xml中配置AnnotationConfigApplicationContext)

過去,您通常要利用 XmlWebApplicationContext 上下文來配置 Spring Web 應用程序,即在 Web 部署描述符文件 web.xml 中指定外部 XML 上下文文件的路徑。XMLWebApplicationContext 是 Web 應用程序使用的默認上下文類。以下代碼描述了 web.xml 中指向將由 ContextLoaderListener 監聽器類載入的外部 XML 上下文文件的元素。

<web-app>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    <servlet>
    <servlet-name>sampleServlet</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    </servlet>

...
</web-app>

現在,您要將 web.xml 中的上述代碼更改爲使用 AnnotationConfigApplicationContext 類。切記,XmlWebApplicationContext 是 Spring 爲 Web 應用程序使用的默認上下文實現,因此您永遠不必在您的web.xml 文件中顯式指定這個上下文類。現在,您將使用基於 Java 的配置,因此在配置 Web 應用程序時,需要在web.xml 文件中指定 AnnotationConfigApplicationContext 類。上述代碼將修改如下:

<web-app>
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.
            support.AnnotationConfigWebApplicationContext
        </param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            demo.AppContext
        </param-value>
    </context-param>
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    <servlet>
    <servlet-name>sampleServlet</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <init-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.
            support.AnnotationConfigWebApplicationContext
        </param-value>
    </init-param>
    </servlet>

...
</web-app>

以上修改後的 web.xml 現在定義了 AnnotationConfigWebApplicationContext 上下文類,並將其作爲上下文參數和 servlet 元素的一部分。上下文配置位置現在指向 AppContext 配置類。這非常簡單。下一節將演示 bean 的生命週期回調和範圍的實現。

@Configuation總結

@Configuation等價於 <Beans></Beans>
@Bean等價於<Bean></Bean>
@ComponentScan等價於<context:component-scan base-package="com.dxz.demo"/>

組合多個配置類

在@configuration中引入spring的xml配置文件

配置類

package test;

import org.springframework.context.annotation.*;
import test2.Config;

@Configuration
@ImportResource("classpath:xspringmvc-servlet.xml")
@ComponentScan(basePackages = "test")
public class BeansContainer {
    public BeansContainer(){
        System.out.println("啓動spring容器");
    }
}

xml文件

<?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 https://www.springframework.org/schema/context/spring-context.xsd">


    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 支持的其中一個屬性,支持的最大文件大小,以字節爲單位 -->
        <property name="maxUploadSize" value="100000"/>
    </bean>
    <bean 
</beans>

這裏很遺憾,我想添加以上bean時,會報錯,可能跟依賴有關係,導入自己的bean是可以的。

在@configuration中引入其它註解配置

配置類

package test;

import org.springframework.context.annotation.*;
import test2.Config;


@Configuration
@Import(Config.class)
@ComponentScan(basePackages = "test")
public class BeansContainer {
    public BeansContainer(){
        System.out.println("啓動spring容器");
    }

}

package test2;

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

@Configuration
public class Config {
    public Config(){
        System.out.println("啓動Config容器");
    }
    @Bean
    public Student student(){
        return new Student();
    }


}

@configuration嵌套(嵌套的Configuration必須是靜態類)

通過配置類嵌套的配置類,達到組合多個配置類的目的。但注意內部類必須是靜態類

package test;

import org.springframework.context.annotation.*;
import test2.Config;


@Configuration
@ComponentScan(basePackages = "test")
public class BeansContainer {
    public BeansContainer(){
        System.out.println("啓動spring容器");
    }

    @Configuration
    static class innerBeansContainer{
        public innerBeansContainer(){
            System.out.println("啓動BeansContainer容器");
        }
        @Bean
        public boss boss(){
            return new boss();
        }

    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章