Spring註解配置

簡介

Spring對於能夠用xml配置實現的基本都提供了註解支持,下面就經過一個實例來介紹一下怎樣使用Spring的註解來代替xml配置。java

AppConfig

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = {"cn.freemethod.spring.bean","cn.freemethod.spring.util","cn.freemethod.spring.aspectscan"})
@ImportResource("classpath:context.xml")
@PropertySource(value = { "classpath:db.properties" , "classpath:dubbo.properties"},ignoreResourceNotFound = true)
public class AppConfig {
 
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
    
}

經過xml配置文件須要一個配置文件,一樣使用註解就須要配置註解類,配置註解類使用@Configuration註解來代表這是一個配置類。 @EnableAspectJAutoProxy註解是對Aspect的註解支持。 @ComponentScan註解配置要掃描的包。 @ImportResource是導入xml配置,使註解和xml配置能夠結合使用。 @PropertySource能夠加載properties文件 @Bean是代表獲取一個實例的方法mysql

要使用@PropertySource必需要有一個PropertySourcesPlaceholderConfigurer實例,這樣就能夠在須要的地方使用@Value等註解。spring

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

import cn.freemethod.spring.aspectscan.AspectS;
import cn.freemethod.spring.aspectscan.DoSomething;
import cn.freemethod.spring.bean.AppBean;
import cn.freemethod.spring.bean.DubboBean;
import cn.freemethod.spring.config.AppConfig;

public class AnnotationConfigStart {
    
    public static void main(String[] args) {
        AbstractApplicationContext  context = new AnnotationConfigApplicationContext(AppConfig.class);
        AppBean appBean = context.getBean(AppBean.class);
        System.out.println(appBean);
        DubboBean dubboBean = context.getBean(DubboBean.class);
        System.out.println(dubboBean);
        AspectS aspectS = context.getBean(AspectS.class);
        System.out.println(aspectS);
        
        DoSomething doSomething = context.getBean(DoSomething.class);
        doSomething.doSomething();
        context.close();
    }

}

加載xml的配置文件能夠使用一個ClassPathXmlApplicationContext類,加載註解配置能夠使用AnnotationConfigApplicationContext類。sql

工程部分目錄

測試的包的部分結構如上圖所示,其餘類請參考下面具體的類代碼,下面是測試輸出:apache

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
appConfig
org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor
org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor
appBean
dubboBean
applicationContextProvider
aspectA
aspectB
aspectS
doSomethingImpl
propertySourcesPlaceholderConfigurer
xmlConfigBean
org.springframework.aop.config.internalAutoProxyCreator
AppBean [url=jdbc:mysql://localhost:3306/design, userName=myuser]
DubboBean [appName=test, dubboProtocol=dubbo, dubboPort=20893]
[cn.freemethod.spring.aspectscan.AspectA@f4d25c6, cn.freemethod.spring.aspectscan.AspectB@11eaf203]
@Before @Order(2)
@Before @Order(5)
doSomething
@After @Order(5)
@After @Order(2)

aspectscan包

public interface AspectBase {

}

AspectBase是一個標記接口。app

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Aspect
@Order(2)
public class AspectA implements AspectBase{
    
    @Before("this(cn.freemethod.spring.aspectscan.DoSomething)")  
    public void aspectABefore(){  
        System.out.println("@Before @Order(2)");  
    }  
      
    @After("this(cn.freemethod.spring.aspectscan.DoSomething)")  
    public void aspectAAfter(){  
        System.out.println("@After @Order(2)");  
    }  

}

AspectA是一個切面,使用的3個註解@Component,@Aspect,@Order(2)。@Component註解代表這是一個組件,@Aspect代表這是一個切面,@Order註解不是像不少資料解釋的是控制加載順序的。@Order標記從spring2.0出現,可是在spring4.0以前,@Order標記只支持AspectJ的切面排序。spring 4.0對@Order作了加強,它開始支持對裝載在諸如Lists和Arrays容器中的自動包裝(auto-wired)組件的排序。maven

能夠修改一下AspectA的@Order值和AspectB的@Order值的大小,觀察一下測試的輸出就能夠知道@Order的做用了。ide

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Aspect
@Order(5)
public class AspectB implements AspectBase{
    
    @Before("this(cn.freemethod.spring.aspectscan.DoSomething)")  
    public void aspectBBefore(){  
        System.out.println("@Before @Order(5)");  
    }  
      
    @After("this(cn.freemethod.spring.aspectscan.DoSomething)")  
    public void aspectAAfter(){  
        System.out.println("@After @Order(5)");  
    }  

}

AspectB也是一個切面,和AspectA同樣。測試

import java.util.List;

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

@Component
public class AspectS {
    
    @Autowired
    private List<AspectBase> aspects ;
    
    @Override
    public String toString(){
        return aspects.toString();
    }

}

AspectS測試@Order注入List的順序。ui

public interface DoSomething {
    
    void doSomething();

}
import org.springframework.stereotype.Service;

@Service
public class DoSomethingImpl implements DoSomething{
    
    public void doSomething(){
        System.out.println("doSomething");
    }

}

上面是2個業務測試相關的接口和類,測試@Order對Aspect切面的執行順序的影響。

bean包

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

@Component
public class AppBean {
    
    @Value("${jdbc.url}")
    private String url;
 
    @Value("${jdbc.username}")
    private String userName;

    @Override
    public String toString() {
        return "AppBean [url=" + url + ", userName=" + userName + "]";
    }
    

}
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class DubboBean {

    @Value("${app.name}")
    private String appName;
    
    @Value("${dubbo.protocol}")
    private String dubboProtocol;
    
    @Value("${dubbo.port}")
    private int dubboPort;

    public String getAppName() {
        return appName;
    }

    public void setAppName(String appName) {
        this.appName = appName;
    }

    public String getDubboProtocol() {
        return dubboProtocol;
    }

    public void setDubboProtocol(String dubboProtocol) {
        this.dubboProtocol = dubboProtocol;
    }

    public int getDubboPort() {
        return dubboPort;
    }

    public void setDubboPort(int dubboPort) {
        this.dubboPort = dubboPort;
    }

    @Override
    public String toString() {
        return "DubboBean [appName=" + appName + ", dubboProtocol=" + dubboProtocol + ", dubboPort=" + dubboPort + "]";
    }
    
}

上面2個Bean測試@PropertySource註解和@Value註解。從輸出的結果中咱們能夠看到把配置文件中的值注入到了字段中。

util

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class ApplicationContextProvider implements ApplicationContextAware {

    private static ApplicationContext context;

    public void setApplicationContext(ApplicationContext context) throws BeansException {
        ApplicationContextProvider.context=context;
        String[] names = context.getBeanDefinitionNames();
        for(String name : names){
            System.out.println(name);
        }
    }

    public static ApplicationContext getApplicationContext() {
        return context;
    }

}

ApplicationContextProvider類實現了ApplicationContextAware接口是爲了獲取ApplicationContext,能夠經過ApplicationContext獲取工廠中的類。看到有那些類被加載初始化了。

xml

public class XmlConfigBean {

}

配置

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

    <bean id="xmlConfigBean" class="cn.freemethod.spring.xml.XmlConfigBean" />
    
</beans>

db.properties

jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/design
jdbc.username = myuser
jdbc.password = mypassword

dubbo.properties

cache.path=/usr/home/test
app.owner.name = test
app.organization.name = freemethod
app.name = test
dubbo.protocol = dubbo
dubbo.port=20893
dubbo.registry.address=127.0.0.1:2181
dubbo.registry.protocol=zookeeper
connect.service.max.thread.threads.size =200

附錄

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>cn.freemethod</groupId>
  <artifactId>config</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <properties>
        <spring_version>4.1.6.RELEASE</spring_version>
        <cglib_version>3.2.4</cglib_version>
        <javassist_version>3.12.1.GA</javassist_version>
        <junit_version>4.9</junit_version>
    </properties>
  
  <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring_version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring_version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring_version}</version>
        </dependency>
        
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit_version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring_version}</version>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.7.3</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.11</version>
        </dependency>
  </dependencies>
</project>
相關文章
相關標籤/搜索