小白学习后端开发之Spring框架注解大全(一)

    技术2025-05-30  12

    一、Spring 初次尝试

    1、通过xml形式配置IOC容器Bean

    在Project下面找到一个resources 文件夹创建一个beans.xml (xml的文件名随意)。如下,把你需要加载的bean 插入到bean节点下面。定义id 和 class类。当application被创建的时候,他就会去扫对应的xml文件,将这里定义的bean加载到IOC容器。

    <?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="person" class="lsn01.cap01.Person"> <property name="name" value="jack"/> <property name="age" value="19"/> </bean> </beans>

    测试方式:(xml形式 需要使用ClassPathXmlApplicationContext)

    ApplicationContext appxml = new ClassPathXmlApplicationContext("beans.xml"); Person person = appxml.getBean("person", Person.class); System.out.println(person.toString());

    2、通过注解的形式加载bean

    注解1:@Configuration 作用于类,被这个注解标注的类可以理解成beans.xml 注解2:@Bean 作用于方法,主要作用往IOC容器中注册一个Bean, 值是id 返回值是Bean的类型

    @Configuration public class MainConfig { @Bean("springPerson") public Person getPerson(){ return new Person("spring",17); } }

    测试方式:

    ApplicationContext app = new AnnotationConfigApplicationContext(MainConfig.class); Person springPerson = (Person) app.getBean("springPerson"); System.out.println(springPerson.toString()); String[] beanNamesForType = app.getBeanNamesForType(Person.class); for (String name : beanNamesForType) { System.out.println(name); }

    作为一个小白,第一次看到这样的操作注解,并不知道这里有什么作用。

    Spring Bean和Configuration 升级

    1、ComponentScan 定义扫描组件规则

    通过注解我们可以定义配置类也就是Configuration可以扫描到那些类。以MVC为例我一般会定义 Controller、Service、Dao。 所以我们会定义很多这些相关的类,但是并不是所有类都需要加载到IOC容器。所谓Component 其实Controller、Service、Dao(Repository) 都是Component没有本质上的区别,就是一个类,注解被标记的时候,表明它的作用,起到一个提示作用。 如下目录结构:

    -test2 -controller OrderControlller.java -dao OrderDao.java -service OrderService.java

    @Controller public class OrderControlller { } @Repository public class OrderDao { } @Service public class OrderService { }

    接下来定义配置类

    @Configuration @ComponentScan(value = {"lsn01.cap02"}, includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}) }, useDefaultFilters = false) public class Cap01MainConfig { }

    定义测试方式:

    @Test public void testComponentScan(){ ApplicationContext app = new AnnotationConfigApplicationContext(Cap02MainConfig.class); String[] beanDefinitionNames = app.getBeanDefinitionNames(); for (String beanDefinitionName : beanDefinitionNames) { System.out.println("beanDefinitionName = "+beanDefinitionName); } }

    ComponentScan注解主要属性,

    1、value 配置扫码的包路径String[] value() default {}

    2、includeFilters 包含哪些Filter。 可以通过定义type 和classs 指定哪些可以被扫描到。 如:@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class}) 打印结果:

    beanDefinitionName = org.springframework.context.annotation.internalConfigurationAnnotationProcessor beanDefinitionName = org.springframework.context.annotation.internalAutowiredAnnotationProcessor beanDefinitionName = org.springframework.context.annotation.internalCommonAnnotationProcessor beanDefinitionName = org.springframework.context.event.internalEventListenerProcessor beanDefinitionName = org.springframework.context.event.internalEventListenerFactory beanDefinitionName = cap02MainConfig beanDefinitionName = orderControlller beanDefinitionName = orderDao beanDefinitionName = orderService

    显然并没有起到一个过滤效果,依然把所有的组件全部扫描进来,而我们需要的只是包含Controller注解的类。 原因在于 useDefaultFilters = false 设置,关闭到默认的Filters

    beanDefinitionName = org.springframework.context.annotation.internalConfigurationAnnotationProcessor beanDefinitionName = org.springframework.context.annotation.internalAutowiredAnnotationProcessor beanDefinitionName = org.springframework.context.annotation.internalCommonAnnotationProcessor beanDefinitionName = org.springframework.context.event.internalEventListenerProcessor beanDefinitionName = org.springframework.context.event.internalEventListenerFactory beanDefinitionName = cap02MainConfig beanDefinitionName = orderControlller

    3、excludeFilters 不包含哪些Filters 注意:如果使用这个注解就不需要将设置成true 否则将不会扫描任何组件 如:

    excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Service.class}), useDefaultFilters = false

    打印结果:

    beanDefinitionName = org.springframework.context.annotation.internalConfigurationAnnotationProcessor beanDefinitionName = org.springframework.context.annotation.internalAutowiredAnnotationProcessor beanDefinitionName = org.springframework.context.annotation.internalCommonAnnotationProcessor beanDefinitionName = org.springframework.context.event.internalEventListenerProcessor beanDefinitionName = org.springframework.context.event.internalEventListenerFactory beanDefinitionName = cap02MainConfig

    4、自定义Filters

    public class CustomFilter implements TypeFilter { public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { //当前扫描类的注解信息 AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); Set<String> annotationTypes = annotationMetadata.getAnnotationTypes(); for (String annotationType : annotationTypes) { System.out.println("annotationType : "+annotationType); } //当前扫描类的类的信息 ClassMetadata classMetadata = metadataReader.getClassMetadata(); String className = classMetadata.getClassName(); System.out.println("classMetadata className = "+className); //当前扫描类的资源 Resource resource = metadataReader.getResource(); String filename = resource.getFilename(); System.out.println("filename = "+filename); //返回true就是包含,false就是不包含 return false; } }

    相关的自定义可以根据上面的三种信息定义属于的结果逻辑返回。

    打印结果

    classMetadata className = lsn01.cap02.config.CustomFilter filename = CustomFilter.class annotationType : org.springframework.stereotype.Controller classMetadata className = lsn01.cap02.controller.OrderControlller filename = OrderControlller.class annotationType : org.springframework.stereotype.Repository classMetadata className = lsn01.cap02.dao.OrderDao filename = OrderDao.class annotationType : org.springframework.stereotype.Service classMetadata className = lsn01.cap02.service.OrderService filename = OrderService.class beanDefinitionName = org.springframework.context.annotation.internalConfigurationAnnotationProcessor beanDefinitionName = org.springframework.context.annotation.internalAutowiredAnnotationProcessor beanDefinitionName = org.springframework.context.annotation.internalCommonAnnotationProcessor beanDefinitionName = org.springframework.context.event.internalEventListenerProcessor beanDefinitionName = org.springframework.context.event.internalEventListenerFactory beanDefinitionName = cap02MainConfig

    1、从打印结果上看我们可以看到 最先扫描的是CustomFilter 2、FilterType.ANNOTATION:按照注解 FilterType.ASSIGNABLE_TYPE:按照给定的类型;比如按BookService类型 FilterType.ASPECTJ:使用ASPECTJ表达式 FilterType.REGEX:使用正则指定 FilterType.CUSTOM:使用自定义规则,自已写类,实现TypeFilter接口>

    2、scope 定义扫描规则

    scope 主要作用是定义Bean在IOC容器中的创建规则 prototype: 多实例:IOC容器启动并不会去调用方法创建对象放在容器中,而是每次获取的时候才会调用方法创建对象 singleton: 单实例(默认),IOC容器启动会调用方法创建对象放到IOC容器中以后每交获取就是直接从容器(理解成从map.get对象)中拿 request: 主要针对WEB应用,同一次请求创建一个实例 session: 同一个session创建一个实例

    @Configuration public class Cap02MainConfig { @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Bean public Person person(){ System.out.println("创建了一个person对象"); return new Person(); } } @Test public void testScope(){ ApplicationContext app = new AnnotationConfigApplicationContext(Cap02MainConfig.class); System.out.println("IOC容器初始化完成了"); Person person1 = app.getBean("person", Person.class); Person person2 = app.getBean("person", Person.class); System.out.println("person1 == person2 is "+(person2 == person1)); }

    打印结果: 如果不加,@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

    创建了一个person对象 IOC容器初始化完成了 person1 == person2 is true

    加@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

    IOC容器初始化完成了 创建了一个person对象 创建了一个person对象 person1 == person2 is false

    得出结论默认情况在AnnotationConfigApplicationContext创建的时候,Spring自动就完成了所有相关bean的创建,并且是单例类;如果加入Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 是多实例类,并且不是随着ApplicationContext的创建而创建。

    3、lazy懒加载

    @Configuration public class Cap02MainConfig { //@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Lazy @Bean public Person person(){ System.out.println("创建了一个person对象"); return new Person(); } } @Test public void testScope(){ ApplicationContext app = new AnnotationConfigApplicationContext(Cap02MainConfig.class); System.out.println("IOC容器初始化完成了"); Person person1 = app.getBean("person", Person.class); Person person2 = app.getBean("person", Person.class); System.out.println("person1 == person2 is "+(person2 == person1)); }

    打印结果:

    IOC容器初始化完成了 创建了一个person对象 person1 == person2 is true
    Processed: 0.010, SQL: 9