Spring (2) Spring 注解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/CoderTnT/article/details/89306847

Spring注解常用汇总

1、使用注解之前要开启自动扫描功能

那么Spring是如何启动自动扫描的?

在这里列举出三种启动自动扫描的方式.

方式一:

此种情况下,针对比较特殊的情形,即项目中运用了SpringBoot,则可以利用@SpringBootApplication注解的方式启动自动扫描功能.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

方式二:

通过XML配置方式,启动自动扫描功能.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 http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.lc" />
</beans>

其中base-package为需要扫描的包(含子包)

标签将会开启Spring Beans的自动扫描,并可设置base-package属性,表示Spring将会扫描该目录以及子目录下所有被@Component标注修饰的类,对它们进行装配。

方式三:

通过Java配置方式,启动自动扫描功能.

关于@Configuration和@ComponentScan两个注解: 
(1)@Configuration表示这个Java文件是一个配置文件,这类Java代码的作用在于配置,要和普通的Java代码区分开放,因此一般我们需要将其放在一个专门的包中,在代码例子中是com.lc.config。

(2)@ComponentScan表示开启Spring Beans扫描,类似于XML配置,这里也可以可以设置basePackages属性。 
如果@ComponentScan注解没有显示去给其他的属性赋值的话,比如此处给basePackages赋值了,如果没有的话,@ComponentScan注解会扫描与配置类相同的包.
 

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.lc.config")
public class BlogSystemConfig {
    /**
     * 在这里实现java方式的配置,
     */
}

在这里给出一个具体的实例:

import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "com.lc.config")
public class DataSourceConfig {

    @Bean(name="dataSource")//java配置方式,配置数据源(dataSource)
    public BasicDataSource dataSource(){
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName("org.postgresql.Driver");
        dataSource.setUrl("jdbc:postgresql://127.0.0.1:5432/center_db?useUnicode=true&characterEncoding=UTF-8");
        dataSource.setUsername("postgres");
        dataSource.setPassword("123456");
        dataSource.setInitialSize(5);
        dataSource.setMaxActive(10);
        return dataSource;
    }

}


@Configuration把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。 
@Scope注解                    作用域 
@Lazy(true)                     表示延迟初始化 
@Service                         用于标注业务层组件、 
@Controller                     用于标注控制层组件(如struts中的action) 
@Repository                    用于标注数据访问组件,即DAO组件。 
@Component                  泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。 
@Scope                          用于指定scope作用域的(用在类上) 
@PostConstruct              用于指定初始化方法(用在方法上) 
@PreDestory                   用于指定销毁方法(用在方法上) 
@Resource                      默认按名称装配,当找不到与名称匹配的bean才会按类型装配。 
@DependsOn                  定义Bean初始化及销毁时的顺序 
@Primary                        自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常 

在spring 中使用注解,常使用@Autowired, 默认是根据类型Type来自动注入的。但有些特殊情况,对同一个接口,可能会有几种不同的实现类,而默认只会采取其中一种的情况下 @Primary 的作用就出来了。下面是个简单的使用例子。

有如下一个接口

public interface Singer {
    String sing(String lyrics);
}

有下面的两个实现类:

@Component // 加注解,让spring识别
public class MetalSinger implements Singer{

    @Override
    public String sing(String lyrics) {
        return "I am singing with DIO voice: "+lyrics;
    }
}
//注意,这里没有注解
public class OperaSinger implements Singer {
    @Override
    public String sing(String lyrics) {
        return "I am singing in Bocelli voice: "+lyrics;
    }
}

下面就是注入上面的

@Component
 public class SingerService {
        private static final Logger logger = LoggerFactory.getLogger(SingerService.class);
    @Autowired
    private Singer singer;
    public String sing(){
        return singer.sing("song lyrics");
    }
   }

执行后的结果:

I am singing with DIO voice: song lyrics.

原因很简单,就是 OperaSinger 这个类上面根本没有加上注解@Copmonent 或者 @Service, 所以spring 注入的时候,只能找到 MetalSinger 这个实现类. 所以才有这个结果。

但是如果一旦 OperaSinger 这个类加上了@Copmonent 或者 @Service 注解,有趣的事情就会发生,你会发现一个错误的结果或异常: 
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [main.service.Singer] is defined: expected single matching bean but found 2: metalSinger,operaSinger

提示很明确了,spring 根据类型无法选择到底注入哪一个。这个时候@Primay 可以闪亮登场了。

@Primary
@Component
public class OperaSinger implements Singer{

    @Override
    public String sing(String lyrics) {
        return "I am singing in Bocelli voice: "+lyrics;
    }
}

如果代码改成这样,再次运行,结果如下: 
“I am singing in Bocelli voice: song lyrics”, 用@Primary 告诉spring 在犹豫的时候优先选择哪一个具体的实现。

第二种方式保证实例有资格的qualifying bean:

用@Qualifier这个注解来解决问题

将上面的两个类改为如下:

@Component // 加注解,让spring识别
@Qualifier("metalSinger")
public class MetalSinger implements Singer{

    @Override
    public String sing(String lyrics) {
        return "I am singing with DIO voice: "+lyrics;
    }
}

@Component
@Qualifier("opreaSinger")
public class OperaSinger implements Singer {
    @Override
    public String sing(String lyrics) {
        return "I am singing in Bocelli voice: "+lyrics;
    }
}
@Component
public class SingerService {
    private static final Logger logger = LoggerFactory.getLogger(SingerService.class);

    @Autowired
    private Singer singer;

    @Qualifier("opreaSinger")
    public String sing(){
        return singer.sing("song lyrics");
    }
}

@Autowired                     默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用 
@Autowired @Qualifier(“personDaoBean”)    存在多个实例配合使用

猜你喜欢

转载自blog.csdn.net/CoderTnT/article/details/89306847