Spring IoC注解式开发

Spring IoC注解式开发


一、声明Bean的注解

  • 负责声明 Bean(xml配置中的bean标签的作用是一样的) 的注解,常见的包括四个:
    • @Component
    • @Controller 控制器类上使用
    • @Service service类上使用
    • @Repository dao类上使用
  • @Controller@Service@Repository这三个注解都是@Component注解的别名。也就是说:这四个注解的功能都一样。用哪个都可以。只是为了增强程序的可读性。
  • 他们都是只有一个value属性。value属性用来指定bean的id,也就是bean的名字。

1.@Component

java 复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
	String value() default "";
}

2.@Controller

java 复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
	@AliasFor(annotation = Component.class)
	String value() default "";
}

3.@Service

java 复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
	@AliasFor(annotation = Component.class)
	String value() default "";
}

4.@Repository

java 复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
	@AliasFor(annotation = Component.class)
	String value() default "";
}

二、Spring注解的使用

  • 如何使用以上的注解呢?

    • 第一步:加入aop的依赖
      • 当加入spring-context依赖之后,会关联加入aop的依赖。
    • 第二步:在配置文件中添加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"
           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">
    </beans>
    • 第三步:在配置文件中指定扫描的包
      • 如果是多个包怎么办,有两种解决方案:
        • 第一种:在配置文件中指定多个包,用逗号隔开。
        • 第二种:指定多个包的共同父包。
    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.powernode.spring6.bean"/>
    </beans>
    • 第四步:在Bean类上使用注解
      • 注解的属性名是value,那么value是可以省略的。
      • 如果把value属性彻底去掉,spring会为Bean自动取名,并且默认名字的规律是:Bean类名首字母小写即可。
    java 复制代码
    package com.gdb.spring6.bean;
    
    import org.springframework.stereotype.Component;
    
    //@Component(value = "userBean")和下面的效果是一样的
    @Component 
    public class User {
    }

三、选择性实例化Bean

  • 假设在某个包下有很多Bean,有的Bean上标注了Component,有的标注了Controller,有的标注了Service,有的标注了Repository,现在由于某种特殊业务的需要,只允许其中所有的Controller参与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">
    	<!-- 
    		use-default-filters="true" (默认值)表示:使用spring默认的规则,只要有Component、Controller、Service、Repository中的任意一个注解标注,则进行实例化。
    		use-default-filters="false" 表示:不再spring默认实例化规则,即使有Component、Controller、Service、Repository这些注解标注,也不再实例化。
    	 -->
        <context:component-scan base-package="com.gdb.spring6.bean3" use-default-filters="false">
            <!-- 表示只有Controller进行实例化。 -->
            <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
    </beans>
    xml 复制代码
    <!-- 也可以将use-default-filters设置为true(不写就是true),并且采用exclude-filter方式排出哪些注解标注的Bean不参与实例化: -->
    <context:component-scan base-package="com.powernode.spring6.bean3">
      <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
      <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
      <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

四、负责注入的注解

  • @Component@Controller @Service @Repository 这四个注解是用来声明Bean的,声明后这些Bean将被实例化。接下来我们看一下,如何给Bean的属性赋值。给Bean属性赋值需要用到这些注解:

1.@Value

java 复制代码
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {
	String value();
}
  • 当属性的类型是简单类型时,可以使用@Value注解进行注入。
  • 注解 @Value的语法格式:@Value(${"key:默认值"})

2.@Autowired和@Qualifier

java 复制代码
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
	boolean required() default true;
}
java 复制代码
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
	String value() default "";
}
  • @Autowired注解有一个required属性,默认值是true,表示在注入的时候要求被注入的Bean必须是存在的,如果不存在则报错。如果required属性设置为false,表示注入的Bean存在或者不存在都没关系,存在的话就注入,不存在的话,也不报错。
  • @Autowired注解可以用来注入非简单类型。单独使用@Autowired注解,默认根据类型装配。【默认是byType】
  • @Autowired注解和@Qualifier注解联合起来才可以根据名称进行装配,在@Qualifier注解中指定Bean名称。

3.@Resource

java 复制代码
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
@Repeatable(Resources.class)
public @interface Resource {
    String name() default "";
    String lookup() default "";
    Class<?> type() default java.lang.Object.class;
    enum AuthenticationType {
	    CONTAINER,
	    APPLICATION
    }
    AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
    boolean shareable() default true;
    String mappedName() default "";
    String description() default "";
}
  • @Resource注解也可以完成非简单类型注入。那它和@Autowired注解有什么区别?

    • @Resource注解是JDK扩展包中的,也就是说属于JDK的一部分。所以该注解是标准注解,更加具有通用性。(JSR-250标准中制定的注解类型。JSR是Java规范提案。)
    • @Autowired注解是Spring框架自己的。
    • @Resource注解默认根据名称装配byName,未指定name时,使用属性名作为name。通过name找不到的话会自动启动通过类型byType装配。
    • @Autowired注解默认根据类型装配byType,如果想根据名称装配,需要配合@Qualifier注解一起用。
  • @Resource注解属于JDK扩展包,所以不在JDK当中,需要额外引入以下依赖:【如果是JDK8的话不需要额外引入依赖。高于JDK11或低于JDK8需要引入以下依赖。】

    xml 复制代码
    <dependency>
      <groupId>jakarta.annotation</groupId>
      <artifactId>jakarta.annotation-api</artifactId>
      <version>2.1.1</version>
    </dependency>

五、全注解式开发

  • 所谓的全注解开发就是不再使用spring配置文件了。写一个配置类来代替配置文件

    java 复制代码
    package com.gdb.spring6.config;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.ComponentScans;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ComponentScan({"com.gdb.spring6.dao", "com.gdb.spring6.service"})
    public class Spring6Configuration {
    }
  • 编写测试程序:不再new ClassPathXmlApplicationContext()对象了。

    java 复制代码
    @Test
    public void testNoXml(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Spring6Configuration.class);
        UserService userService = applicationContext.getBean("userService", UserService.class);
        userService.save();
    }

1.@Configuration

java 复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
	@AliasFor(annotation = Component.class)
	String value() default "";
	boolean proxyBeanMethods() default true;
	boolean enforceUniqueMethods() default true;
}
  • 注意:@Configuration包含有@Component注解的功能。
  • @Configuration注解用于标识一个类作为配置类(可以代替XML配置文件),它通常与@Bean注解一起使用。配置类是Spring IoC容器的一部分,它定义了一组Bean的创建和配置规则。

2.@Bean

java 复制代码
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
	@AliasFor("name")
	String[] value() default {};
	@AliasFor("value")
	String[] name() default {};
	boolean autowireCandidate() default true;
	String initMethod() default "";
	String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
}
  • Spring的@Bean注解用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。 产生这个Bean对象的方法Spring只会调用一次,随后这个Spring将会将这个Bean对象放在自己的IOC容器中。
  • @Component , @Repository , @ Controller , @Service 这些注解只局限于自己编写的类,而@Bean注解能把第三方库中的类实例加入IOC容器中并交给spring管理。
  • @Bean注解和xml配置中的bean标签的作用是一样的。

3.@ComponentScan

java 复制代码
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
	@AliasFor("basePackages")
	String[] value() default {};
	@AliasFor("value")
	String[] basePackages() default {};
	Class<?>[] basePackageClasses() default {};
	Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
	Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
	ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
	String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;
	boolean useDefaultFilters() default true;
	Filter[] includeFilters() default {};
	Filter[] excludeFilters() default {};
	boolean lazyInit() default false;
	@Retention(RetentionPolicy.RUNTIME)
	@Target({})
	@interface Filter {
		FilterType type() default FilterType.ANNOTATION;
		@AliasFor("classes")
		Class<?>[] value() default {};
		@AliasFor("value")
		Class<?>[] classes() default {};
		String[] pattern() default {};
	}
}
  • @ComponentScan注解顾名思义就是扫描声明了@Component注解的类,然后注入到Spring容器中的。
  • @ComponentScan注解和xml配置中的ComponentScan标签的作用是一样的。

相关推荐
战神刘玉栋11 分钟前
《基于 defineProperty 实现前端运行时变量检测》
前端
嘻嘻哈哈1733 分钟前
vue安装+测试
前端·javascript·vue.js
大学生小郑39 分钟前
VUE与React的生命周期对比
前端·vue.js·react.js
伏颜.39 分钟前
Spring懒加载Bean机制
java·spring
细心的莽夫40 分钟前
集合复习(java)
java·开发语言·笔记·学习·java-ee
JerryXZR44 分钟前
Angular基础保姆级教程 - 1
前端·javascript·angular.js
金灰1 小时前
14-Django项目--文件上传-Excel
服务器·前端·javascript
yours_Gabriel1 小时前
java基础:面向对象(二)
java·开发语言·笔记·学习
Enaium1 小时前
Rust入门实战 编写Minecraft启动器#3解析资源配置
java·开发语言·rust
inksci1 小时前
用 Echarts 画折线图
前端·javascript·html·echarts