Spring最常用组件注册注解开发案例

Spring常用组件注册注解开发案例

什么是spring注解开发?

就是不再使用Spring的bean.xml文件,纯使用注解的方式开发;

要使用纯注解开发,就需要有一个配置类,配置类==配置文件

spring版本:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.1.5.RELEASE</version>
</dependency>

1. 组件注册注解

1. @Configuration

@Configuration:一旦在某个类上标注了此注解,说明此类就是一个配置类

注解的定义如下:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}

2.@Bean注解

@Bean:给容器中注册一个bean;类型为返回值的类型,id默认使用方法名作为id

注解的定义如下:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.core.annotation.AliasFor;

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
    @AliasFor("name")
    String[] value() default {};

    @AliasFor("value")
    String[] name() default {};

    /** @deprecated */
    @Deprecated
    Autowire autowire() default Autowire.NO;

    boolean autowireCandidate() default true;

    String initMethod() default "";

    String destroyMethod() default "(inferred)";
}

3. @Configuration与@Bean注解使用案例

定义一个名为Person的类,如下

package com.yuan.bean;

public class Person {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
  • 传统的方式实现注册一个bean的方式:

    1.编写spring的核心配置文件,如bean.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 ">
        <!--包扫描xml配置:只要标注了@Controller、@Service、@Repository、@Component等注解,它们会自动的加载到IOC容器中-->
        <!--<context:component-scan base-package="com.yuan"></context:component-scan>-->
        <!--使用set方式赋值-->
        <bean id="person" class="com.yuan.bean.Person">
            <property name="age" value="22" />
            <property name="name" value="jinshengyuan"/>
        </bean>
    </beans>
    
    1. 加载spring核心配置文件 bean.xml文件来初始化一个Person类
    package com.yuan;
    
    import com.yuan.bean.Person;
    import com.yuan.config.MainConfig;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MainTest {
        public static void main(String[] args) {
            //xml配置的方式
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
            Person person = (Person) applicationContext.getBean("person");
            System.out.println(person);
            }
        }
    }
    执行结果:Person{name='jinshengyuan', age=22}
    
  • 使用注解驱动开发方式注册一个bean

    1. 编写一个配置类,如下面的MainConfig.java
    package com.yuan.config;
    
    import com.yuan.bean.Person;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    //配置类 == 配置文件
    @Configuration //告诉spring这是一个配置类
    public class MainConfig {
        /**
         * @Bean注解: 给容器中注册一个bean;类型为返回值的类型,id默认使用方法名作为id
         * 如果要自己指定id,则需要加上name属性,如:@bean(value="person"),value可省略写成@Bean("person")
         * @return
         */
        @Bean(name = "person")
        public Person person01(){
            return new Person("张三",20);
        }
    }
    
    1. 初始化bean
    package com.yuan;
    
    import com.yuan.bean.Person;
    import com.yuan.config.MainConfig;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MainTest {
        public static void main(String[] args) {
            //xml配置的方式
            /*ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
            Person person = (Person) applicationContext.getBean("person");
            System.out.println(person);*/
    
            //使用注解的方式为IOC容器注册一个组件
            ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
            Person person = applicationContext.getBean(Person.class);
            System.out.println(person);
            //根据类型获取bean的名称
            String[] beanNamesForType = applicationContext.getBeanNamesForType(Person.class);
            for (int i=0;i<beanNamesForType.length;i++){
                System.out.println(beanNamesForType[i]);
            }
        }
    }
    

4. ComponentScan注解

@ComponentScan:只要标注了@Controller、@Service、@Repository、@Component等注解,它们会通过@ComponentScan自动的加载到IOC容器中

@ComponentScan属性:

  • value:指定自动扫描的包
  • excludeFilters = ComponentScan.Filter[] : 指定扫描的时候按照什么规则排除哪些组件;
  • includeFilters = ComponentScan.Filter[] : 指定扫描的时,只需要包含哪些组件,还需配合与禁用默认规则一起使用;
  • useDefaultFilters = false : 禁用自动扫描的默认规则

@ComponentScan.Filter的属性:

@ComponentScan.Filter的属性type过滤规则
 FilterType.ANNOTATION:按照注解(常用)
 FilterType.ASSIGNABLE_TYPE :按照给定的类型(常用)
 FilterType.ASPECTJ:使用ASPECTJ表达式
 FilterType.CUSTOM :使用自定义规则
 FilterType.REGEX :使用正则表达式指定
  1. xml配置方法:
<context:component-scan base-package="com.yuan"></context:component-scan>
  1. 注解方式:Java8+
package com.yuan.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

@Configuration
@ComponentScan(value = "com.yuan",excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})
},includeFilters = {
    @ComponentScan.Filter(type =FilterType.ANNOTATION,classes = {Service.class})@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes ={BookServices.class}
},useDefaultFilters = false) //自动扫描的包

//excludeFilters = ComponentScan.Filter[] : 指定扫描的时候按照什么规则排除哪些组件
//includeFilters = ComponentScan.Filter[] : 指定扫描的时,只需要包含哪些组件,还需配合禁用掉默认规则一起使用
//useDefaultFilters = false : 禁用自动扫描的的默认规则
//如果是Java8版本,则可以多次使用@ComponentScan注解,如果Java8之前的版本,则使用@ComponentScans注解来多次使用@ComponentScan注解
@ComponentScan(...) //java8中可以写多个@ComponentScan
@ComponentScan(...) //java8中可以写多个@ComponentScan
public class MyConfigOne {
    @Bean("person")
    public Person person(){
        return new Person("李四",25);
    }
}
  1. 注解方式:Java8以下版本要配置多个@ComponentScan时使用@ComponentScans注解来做
package com.yuan.config;

import com.yuan.bean.Person;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

@Configuration
@ComponentScans(
        value = {
                @ComponentScan(value = "com.yuan", excludeFilters = {
                        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
                }, includeFilters = {
                        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Service.class})
                }, useDefaultFilters = false) //自动扫描的包
        }
)
//excludeFilters = ComponentScan.Filter[] : 指定扫描的时候按照什么规则排除哪些组件
//includeFilters = ComponentScan.Filter[] : 指定扫描的时,只需要包含哪些组件,还需配合禁用掉默认规则一起使用
//useDefaultFilters = false : 禁用自动扫描的的默认规则
//如果是Java8版本,则可以多次使用@ComponentScan注解,如果Java8之前的版本,则使用@ComponentScans注解来多次使用@ComponentScan注解
public class MyConfigOne {
    @Bean("person")
    public Person person(){
        return new Person("李四",25);
    }
}

5. 自定义TypeFilter指定过滤规则

  1. 编写自定义规则类
package com.yuan.config;

import org.springframework.context.annotation.FilterType;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;

/**
 * @ComponentScan.Filter 的type属性自定义规则类(type = FilterType.CUSTOM),实现了TypeFilter接口
 */
public class MyTypeFilter implements TypeFilter {
    /**
     *
     * @param metadataReader the metadata reader for the target class (读取到的正在扫描的类的信息)
     * @param metadataReaderFactory  a factory for obtaining metadata readers (是一个工厂,可以获取其他任何类的信息)
     * 	* for other classes (such as superclasses and interfaces)
     * @return
     * @throws IOException
     */
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //获取当前类注解信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取当前正在扫描的类的信息,比它的类型式什么,实现了哪些接口等等
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //获取当前类的类名
        String className = classMetadata.getClassName();
        System.out.println("---className---->>>>"+className);
        //获取当前类的资源信息(如类的路径)
        Resource resource = metadataReader.getResource();
        //如果类名中包含er则匹配成功
        if(className.contains("er")){
            return true;
        }

        return false;
    }
}
  1. 自定义规则配置类
package com.yuan.config;

import com.yuan.bean.Person;
import org.springframework.context.annotation.*;

@Configuration
//如果Java8之前的版本,则使用@ComponentScans注解来多次使用@ComponentScan注解
@ComponentScans(
        value = {
                @ComponentScan(value = "com.yuan", includeFilters = {
                        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})
                }, useDefaultFilters = false) //自动扫描的包
        }
)
/*
 @ComponentScan.Filter过滤规则
 FilterType.ANNOTATION:按照注解(常用)
 FilterType.ASSIGNABLE_TYPE :按照给定的类型(常用)
 FilterType.ASPECTJ:使用ASPECTJ表达式
 FilterType.CUSTOM :使用自定义规则
 FilterType.REGEX :使用正则表达式指定
 */
public class MyConfigTwo {
    @Bean(value = "person")
    public Person person() {
        return new Person("张三", 33);
    }
}

  1. 测试
package com.yuan.test;

import com.yuan.config.MainConfig;
import com.yuan.config.MyConfigTwo;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class IOCTest {
    @Test
    public void testTwo(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfigTwo.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
    }
}

  1. 执行结果:
---className---->>>>com.yuan.test.IOCTest
---className---->>>>com.yuan.MainTest
---className---->>>>com.yuan.bean.Person
---className---->>>>com.yuan.config.MainConfig
---className---->>>>com.yuan.config.MyConfigOne
---className---->>>>com.yuan.config.MyTypeFilter
---className---->>>>com.yuan.controller.BookController
---className---->>>>com.yuan.dao.BookDao
---className---->>>>com.yuan.services.BookServices
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory

myConfigTwo   ----配置类自己
person        ----@Bean加载的person类,由容器创建的,所有会看到
下面这三个就是由MyTypeFilter过滤规则进行过滤的类
myTypeFilter
bookController
bookServices
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值