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标签的作用是一样的。

相关推荐
YA3334 小时前
mcp-grafana mcp 使用stdio报错
java·开发语言
z***02604 小时前
SpringBoot创建动态定时任务的几种方式
java·spring boot·spring
i听风逝夜4 小时前
Web 3D地球实时统计访问来源
前端·后端
w***95494 小时前
VScode 开发 Springboot 程序
java·spring boot·后端
iMonster4 小时前
React 组件的组合模式之道 (Composition Pattern)
前端
呐呐呐呐呢4 小时前
antd渐变色边框按钮
前端
兔子撩架构5 小时前
Dubbo 的同步服务调用
java·后端·spring cloud
元直数字电路验证5 小时前
Jakarta EE Web 聊天室技术梳理
前端
wadesir5 小时前
Nginx配置文件CPU优化(从零开始提升Web服务器性能)
服务器·前端·nginx
牧码岛5 小时前
Web前端之canvas实现图片融合与清晰度介绍、合并
前端·javascript·css·html·web·canvas·web前端