日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無先后,達(dá)者為師

網(wǎng)站首頁 編程語言 正文

Spring的純注解配置詳解

作者:ギ 不必 更新時間: 2022-10-29 編程語言

導(dǎo)讀:? ? ? ?

? ?????????我們在剛開始進(jìn)行spring的學(xué)習(xí)時, 大部分都是在applicationContext.xm的配置文件中向IOC容器中注入bean,但是這種方式實(shí)在是有點(diǎn)麻煩,所以從spring的2.5版本開始就引入注解的方式來幫助我們簡化bean的配置,而現(xiàn)在spring版本已經(jīng)升級到5.0以上了,使用注解的方式來進(jìn)行配置bean已經(jīng)越來越普遍,在springboot中更是沒有了applicationContext.xml的配置文件,都是采用注解的方式來進(jìn)行IOC的注入,所以了解如何用注解來進(jìn)行bean的配置變得很重要了。

IOC相關(guān)的注解

@Configuration注解

? ? ? ? 作用:在applicationContext.xml配置文件中我們配置bean都是在<beans></beans>標(biāo)簽中進(jìn)行的,而在純注解的配置中我們不需要applicationContext.xml這個文件,所以在這里Configuration注解就相當(dāng)于applicationContext.xml中的beans標(biāo)簽

? ? ? ? 使用:? 在一個類前加上這個注解即可,該類就相當(dāng)于一個beans標(biāo)簽了

//該類就相當(dāng)于一個空的beans標(biāo)簽了
@Configuration
public class UserDao {
}

啟動容器

????????與通過配置文件啟動容器的方式相同,只不過是使用AnnotationConfigApplicationContext這個實(shí)現(xiàn)類傳入字節(jié)碼對象即可

public class Main {
    public static void main(String[] args) {
    //傳入@Configuration注解所在類的Class對象
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(UserDao.class);
    }
}

@ComponentScan注解(包掃描注解)

????????作用: 我們在使用配置注解(比如@Autowired,@Component等注解,下面會講)時, 如果我們只是在一個方法或者類前寫一個注解,那么spring怎么知道我們要將哪個類交給IOC容器管理呢,所以這個注解的作用就是告訴spring要掃描哪些包下的類,將這些配置了注解的類交給IOC容器管理

? ? ? ? 使用:?在添加了@Configuration的注解類前加上此注解, 并且指定basePackages屬性的值即可.

@Configuration
//basePackages為一個字符串?dāng)?shù)組,指定要進(jìn)行掃描的包
@ComponentScan(basePackages = {包1, 包2, .....})
public class UserDao {
   
}

@Component注解

????????作用:將一個類注入IOC容器中,相當(dāng)于先前配置文件中的bean標(biāo)簽

? ? ? ? 使用:? 在一個類前加上此注解即可, 有一個value參數(shù),作用是指定注入類的名稱,相當(dāng)于bean標(biāo)簽中的id屬性.也可以省略不寫,默認(rèn)為類名首字母小寫名稱,例如Plant類的默認(rèn)名稱為plant

//將Animal類交給IOC容器管理
@Component(value = "animals")
public class Animal {
    public Animal(){
        System.out.println("Animal is creating....");
    }
}

@Controller,@Service,@Repository注解

? ? ? ? 與上面的@Component注解作用與用法一樣,只是幫助我們標(biāo)識此類在項目中的層面罷了,

@Controller常用于控制層(其實(shí)在后面的web開發(fā)中,被它修飾的類中的方法默認(rèn)都是一個Servlet,現(xiàn)在了解即可),@Service用于業(yè)務(wù)層,@Repository用于數(shù)據(jù)操作層。

@Scope注解

? ? ? ? 作用:指定類的制造方式為單例還是單例

? ? ? ? 使用:放置在類前面即可,指定為單例還是多例模式

@Component(value = "animals")
@Scope("singleton")//或者prototype
public class Animal {
    public Animal(){
        System.out.println("Animal is creating....");
    }
}

@PostConstruct,@PreDestroy注解

????????作用:為一個類指定初始化(@PostConstruct)或者銷毀(@PreDestroy)方法,相當(dāng)于bean標(biāo)簽中的init-method和destroy-method方法

? ? ? ? 使用:在一個想要充當(dāng)初始化或者銷毀方法的方法前添加此注解

@Component(value = "animals")
public class Animal {
    public Animal(){
        System.out.println("Animal is creating....");
    }
    
    //初始化方法
    @PostConstruct
    public void init(){
        System.out.println("Animal is initializing...");
    }

    //銷毀方法
    @PreDestroy
    public void destroy(){
        System.out.println("Animal is destroying");
    }
}

測試:

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(UserDao.class);
        Animal animal = applicationContext.getBean(Animal.class);
        //在退出虛擬機(jī)之前銷毀IOC容器
        applicationContext.registerShutdownHook();
    }
}

結(jié)果:

Animal is creating....
Animal is initializing...
Animal is destroying

進(jìn)程已結(jié)束,退出代碼0

DI相關(guān)注解

?@Autowired,@Resource, @Qualifier(需配合Autowired注解使用)注解

? ? ? ? 作用: 這些注解都是用來自動裝配引用類型的注解,裝配的bean必須在IOC容器中存在

? ? ? ? 使用: 在一個setter或者字段名之前都可以添加使用.

//新建一個Person類,Person類有一個類型為Animal的字段animal
public class Person {
    
    //添加到字段之前也是可以的
//    @Autowired
    private Animal animal;

    public Person(){
        System.out.println("Person is creating....");
    }

    //setter方法前也可以,自動裝配該字段
    @Autowired
    public void setAnimal(Animal animal) {
        this.animal = animal;
    }
}

? ? ? ? 區(qū)別:

@Autowired:

@Autowired注解是默認(rèn)首先按照類型裝配的(byType),如果找不到對應(yīng)類型的bean或者找到多個類型相同的bean,則再按照名稱進(jìn)行裝配(byName)。如果想直接指定名稱進(jìn)行裝配則需要配合@Qualifier注解進(jìn)行使用:

首先我們創(chuàng)建兩個類型一樣的bean,一個為animal,一個為animal1

?然后我們在字段animals前添加此注解,由于@Autowired先根據(jù)類型進(jìn)行裝配,但是IOC中有兩個類型相同的bean(animalanimal1),如前面所說,當(dāng)找到多個類型的bean時,@Autowired注解會按照名稱進(jìn)行裝配,所以這里就會按照bean的名稱進(jìn)行裝配,但是這里變量的名稱為animals,而兩個bean的名稱為animal和animal1(與變量名稱不同,因為是按名稱裝配所以裝配不成功),所以這里就會報錯

@Component
public class Person {

    @Autowired
    private Animal animals;
    public Person(){
        System.out.println("Person is creating....");
    }

    public void printAnimal(){
        //打印自動裝配的animals
        System.out.println("animal is" + animals);
    }
}

開啟測試:

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(UserDao.class);
        Person person = applicationContext.getBean(Person.class);
        person.printAnimal();
    }
}

結(jié)果:

警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'person': Unsatisfied dependency expressed through field 'animal1s'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'cn_java_factory.Animal' available: expected single matching bean but found 2: animal,animal1
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'person': Unsatisfied dependency expressed through field 'animal1s'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'cn_java_factory.Animal' available: expected single matching bean but found 2: animal,animal1

但是我們只要將字段名改為"animal"或者"animal1"就會運(yùn)行成功

 @Autowired
//animal1或者animal都可以
 private Animal animal;

結(jié)果:

Person is creating....
animal iscn_java_factory.Animal@3b69e7d1

進(jìn)程已結(jié)束,退出代碼0

還可以直接為@Autowired注解指定以名稱進(jìn)行裝配,這時就要使用@Qualifier注解,例如:

    @Autowired
    @Qualifier("animal")
    private Animal myAnimal;

我們這里使用@Qualifier注解指定@Autowired以指定名稱進(jìn)行裝配(@Qualifier必須配合@Autowired使用),所以@Autowired會找到名稱為"animal"的bean裝配給myAnimal這個屬性。

@Resource

? ? ? ? @Resource注解如果沒有指定name和type屬性則默認(rèn)以名稱進(jìn)行裝配,當(dāng)注解寫在字段上時,默認(rèn)取字段名為指定名稱,如果沒有找到對應(yīng)的bean,則再以類型進(jìn)行自動裝配,如果找不到或者找到多個同一類型的bean則報錯;如果指定name屬性則只會按照名稱進(jìn)行裝配,沒有找到指定的名稱則報錯,如果指定type屬性則只會按照類型進(jìn)行裝配,如果找不到或者找到多個同一類型的bean則報錯;

@Value注解

? ? ? ? 作用:給簡單類型字段進(jìn)行賦值

? ? ? ? 使用:在簡單類型字段前添加即可

@Component
public class Person {

    //為String類型賦值
    @Value("jack")
    private String username;

    @Value("20")
    private int age;

    public Person(){
        System.out.println("Person is creating....");
    }

    public void print(){
        System.out.println("username is " + username + ", age " + age);
    }
}

測試:

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(UserDao.class);
        Person person = applicationContext.getBean(Person.class);
        person.print();
    }
}

結(jié)果:

Person is creating....
username is jack, age 20

進(jìn)程已結(jié)束,退出代碼0

可以看出值已經(jīng)注入進(jìn)去了;

@Value還可以讀取properties配置文件中的值:

1.通過@PropertySource注解將properties文件加載進(jìn)來

@Configuration
@ComponentScan(basePackages = {"cn_java_factory"})
//info.properties為在resources文件夾下的配置文件,最好加上"classpath:"這個前綴
@PropertySource("classpath:info.properties")
public class UserDao {
}

2.通過${屬性名}進(jìn)行引用

@Component
public class Person {
    //hobby為info.properties中的屬性名
    @Value("${hobby}")
    private String hobby;

    @Value("${weight}")
    private int weight;

    @Value("${height}")
    private double height;


    public Person(){
        System.out.println("Person is creating....");
    }

    public void print(){
        System.out.println("weight " + weight + " height" + height + " hobby " + hobby);
    }
}

@Bean注解

? ? ? ? 作用: 將靜態(tài)工廠方法或者實(shí)例工廠方法的返回對象注入到IOC容器中

? ? ? ? 使用: 在工廠方法前加上此注解即可,可通過value指定bean的名稱,如果不進(jìn)行指定的話默認(rèn)為方法名名稱。

@Configuration
@ComponentScan(basePackages = {"cn_java_factory"})
@PropertySource("classpath:info.properties")
public class UserDao {
    //靜態(tài)工廠
    @Bean("animals")
    public static Animal getAnimal(){
        return new Animal();
    }

    //實(shí)例工廠
    @Bean
    public Person getPerson(){
        return new Person();
    }
}

從下圖可以看出@Bean如果沒有指定value值則會使用方法名作為bean的名稱,并且已經(jīng)成功的將工廠方法產(chǎn)生的對象注入到IOC容器中了

?@Import注解

? ? ? ? 當(dāng)我們在被@Configuratin注解修飾的類中寫多個被@Bean修飾的工廠方法時,可能會使修飾的類變得臃腫龐大,所以我們可以通過@Import注解將其它類中的被@Bean修飾的方法名引入進(jìn)來來.

@Configuration
@ComponentScan(basePackages = {"cn_java_factory"})
@PropertySource("classpath:info.properties")
//引入其它類中的被@Bean修飾的工廠方法
@Import(PersonFactory.class)
public class UserDao {
}

PersonFactory類:

public class PersonFactory{
    //靜態(tài)工廠
    @Bean("animals")
    public static Animal getAnimal(){
        return new Animal();
    }

    //實(shí)例工廠
    @Bean
    public Person getPerson(){
        return new Person();
    }
}

結(jié)果:

?可以看出工廠方法返回的對象也被注入到IOC中了

上面這些注解就是我們在spring配置中常用的注解了,感謝您的閱讀!!

原文鏈接:https://blog.csdn.net/qq_62698326/article/details/127577152

欄目分類
最近更新