SpringFrameWork之注解类管理Bean

编程入门 行业动态 更新时间:2024-10-18 16:55:22

SpringFrameWork之<a href=https://www.elefans.com/category/jswz/34/1768912.html style=注解类管理Bean"/>

SpringFrameWork之注解类管理Bean

1 Bean 注解方式的扫描

1.1 .1注解理解

和 XML 配置文件一样,注解本身并不能执行,注解本身仅仅只是做一个标记,具体的功能是框架检测到注解标记的位置,然后针对这个位置按照注解标记的功能来执行具体操作。

1.1.2 扫描理解

Spring 为了知道程序员在哪些地方标记了什么注解,就需要通过扫描的方式,来进行检测。然后根据注解进行后续操作。

使用注解方式:

(1):我们需要在ioc容器里添加的组件上添加上注解,该注解并不能执行,只是后来为了方便让ioc容器知道需要在ioc容器中添加上什么类。

(2):编写配置扫描信息,ioc容器并不是挨着扫描所有包的所有类,来看需要将哪个类添加在容器中,这样效率很慢,我们需要指定哪些包有需要添加的组件。

(3):创建容器....获取bean对象.

1.1.3 应用:

a.准备项目pom文件。

<dependencies>
    <!--spring context依赖-->
    <!--当你引入Spring Context依赖之后,表示将Spring的基础依赖引入了-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>6.0.6</version>
    </dependency>

    <!--junit5测试-->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.3.1</version>
    </dependency>
</dependencies>

b.准备组件类

普通组件

package com.cky;import org.springframework.stereotype.Component;@Component
public class Common {
}

Controller组件

package com.cky;import org.springframework.stereotype.Controller;@Controller
public class UserCon {
}

Service组件

package com.cky;import org.springframework.stereotype.Service;@Service
public class UserSerive {
}

Dao组件 

package com.cky;import org.springframework.stereotype.Repository;@Repository
public class UserDao {
}

c.编写配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:context=""xsi:schemaLocation=" .xsd  .xsd">
<!--方法1:直接导入具体的包 1.包要精准,提高性能!2.会扫描指定的包和子包内容3.多个包可以使用 用逗号分割-->
<!--    <context:component-scan base-package="com.cky"></context:component-scan>-->  <!--导入固定的注解,但是要注意,我们要设置use-default-filters为false,即让基础包下的不生效,接着在追加规则--><context:component-scan base-package="com.cky" use-default-filters="false"><context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/></context:component-scan> <!--排除不扫描的组件context:exclude-filter标签:指定排除规则 --><!-- type属性:指定根据什么来进行排除,annotation取值表示根据注解来排除 --><!-- expression属性:指定排除规则的表达式,对于注解来说指定全类名即可 -->

<!--    <context:component-scan base-package="com.cky">-->
<!--        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>-->
<!--    </context:component-scan>-->
</beans>

d.测试

public class testdemo {@Testpublic void test_01(){//实例化容器ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("demo01.xml");//得到Bean对象UserDao userDao=context.getBean("userDao",UserDao.class);System.out.println(userDao);UserSerive userSerive=context.getBean(UserSerive.class);System.out.println(userSerive);}
}

1.1.4 组件注解区别:

Spring 提供了以下多个注解,这些注解可以直接标注在 Java 类上,将它们定义成 Spring Bean。 

通过查看源码我们得知,@Controller、@Service、@Repository这三个注解只是在@Component注解的基础上起了三个新的名字。

对于Spring使用IOC容器管理这些组件来说没有区别,也就是语法层面没有区别。所以@Controller、@Service、@Repository这三个注解只是给开发人员看的,让我们能够便于分辨组件的作用。

注意:虽然它们本质上一样,但是为了代码的可读性、程序结构严谨!我们肯定不能随便胡乱标记。

1.1.5 组件beanname 问题

在我们使用 XML 方式管理 bean 的时候,每个 bean 都有一个唯一标识——id 属性的值,便于在其他地方引用。现在使用注解后,每个组件仍然应该有一个唯一标识。

默认情况:

类名首字母小写就是 bean 的 id。例如:SoldierController 类对应的 bean 的 id 就是 soldierController。

但是,我们也可以使用value进行配置id

@Repository(value = "userdao")
public class UserDao {
}

1.1.6 总结:

1. 注解方式IoC只是标记哪些类要被Spring管理
2. 最终,我们还需要XML方式或者后面讲解Java配置类方式指定注解生效的包
3. **现阶段配置方式为 注解 (标记)+ XML(扫描)**

2、扩展周期方法和作用域

至于周期方法和作用域具体是什么,可见文章1,在这里不重复介绍。

使用注解的方式来编写周期方法:

A.周期方法声明

public class BeanOne {

  //周期方法要求: 方法命名随意,但是要求方法必须是 public void 无形参列表
  @PostConstruct  //注解制指定初始化方法
  public void init() {
    // 初始化逻辑
  }
}

public class BeanTwo {
  
  @PreDestroy //注解指定销毁方法
  public void cleanup() {
    // 释放资源逻辑
  }
}

B.组件作用域配置

@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON) //单例,默认值
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) //多例  二选一

public class BeanOne {

  //周期方法要求: 方法命名随意,但是要求方法必须是 public void 无形参列表
  @PostConstruct  //注解制指定初始化方法
  public void init() {
    // 初始化逻辑
  }
}

注意:单例的话会在容器关闭的时候进行销毁工作,但是多例不会。 

3、Bean属性赋值:引用类型自动配置(DI)

3.1 场景及实例:

UserController 需要 UserService

UserService需要UserDao

a. 准备组件 并在组件中配置 IOC 和DI

package demo03;import org.springframework.stereotype.Repository;@Repository
public class UserDao {public void show2(){System.out.println("Userdao");}
}
package demo03;import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;@Service
public class UserService {
//    @Autowired
//    @Qualifier(value ="userdao")@Resource(name = "userdao")private UserDao userDao;public void show1(){userDao.show2();System.out.println("UserService");}
}
package demo03;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller
public class UserController {@Autowired
    private UserService userService;public void show(){userService.show1();System.out.println("usercontroller");}
}

b.编写配置文件 确定扫描哪写包

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:context=""xsi:schemaLocation=" .xsd  .xsd">
<context:component-scan base-package="demo03"></context:component-scan>
</beans>

c.编写测试代码:

    @Testpublic void test_03(){//实例化容器ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("demo03.xml");//得到Bean对象UserController userController=context.getBean(UserController.class);userController.show();}

d.结果:

3.2 对实例讲解

3.2.1 @Autowired 注解

在使用注解方式时,我们没必要像 XML方式那样,在组件中写上setter,使用<bean>之后使用配置的方式进行DI配置。只需要在成员变量上加上@Autowired注解即可,不需要提供setXxx()方法。以后我们在项目中的正式用法就是这样。

A.该注解可添加在成员变量上(最常用)

@Service("smallDog")
public class SoldierService {
    
    @Autowired
    private SoldierDao soldierDao;
    
    public void getMessage() {
        soldierDao.getMessage();
    }
}

B. 构造方法上

@Controller(value = "tianDog")
public class SoldierController {
    
    private SoldierService soldierService;
    
    @Autowired
    public SoldierController(SoldierService soldierService) {
        this.soldierService = soldierService;
    }
    ……

C. Set方法上

@Controller(value = "tianDog")
public class SoldierController {

    private SoldierService soldierService;

    @Autowired
    public void setSoldierService(SoldierService soldierService) {
        this.soldierService = soldierService;
    }
    ……

3.2.2 工作流程

- 首先根据所需要的组件类型到 IOC 容器中查找
    - 能够找到唯一的 bean:直接执行装配
    - 如果完全找不到匹配这个类型的 bean:装配失败
    - 和所需类型匹配的 bean 不止一个
        - 没有 @Qualifier 注解:根据 @Autowired 标记位置成员变量的变量名作为 bean 的 id 进行匹配
            - 能够找到:执行装配
            - 找不到:装配失败
        - 使用 @Qualifier 注解:根据 @Qualifier 注解中指定的名称作为 bean 的id进行匹配
            - 能够找到:执行装配
            - 找不到:装配失败 

只有一个bean的我们不讨论,这里仅需要根据类型需查找ioc中是否有该组件类型即可。

下边讨论一下不止一个bean。

比如一个接口,我们的两个类都实现了该接口。那么这两个类与该接口 的instanceof 都为true。

在我们在其它组件中注入该接口时,ioc容器会发现有两个类 都是该接口的实例化组件,此时就会报错,解决方法①:我们可以使用bean id的方式来找到其中一个实例化组件,就是在编写该接口变量时,接口变量的名字写成其中一个组件的id,那么就会根据该id确定其中的一个实例化组件。

方法②:我们可以 在该接口变量的上方,通过@Autowried@Qualifier注解,在后者里边添加上value属性,即我们要选用实例化组件的id。

方法③:我们可以使用@Resource 注解,不过该注解是java的一种规范化技术,

我们在使用该注解时,需要导入依赖

<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>2.1.1</version>
</dependency>

3.2.3 @Resource与@Autowried 区别

@Resource注解也可以完成属性注入。那它和@Autowired注解有什么区别?

- @Resource注解是JDK扩展包中的,也就是说属于JDK的一部分。所以该注解是标准注解,更加具有通用性。(JSR-250标准中制定的注解类型。JSR是Java规范提案。)
- @Autowired注解是Spring框架自己的。
- **@Resource注解默认根据Bean名称装配,未指定name时,使用属性名作为name。通过name找不到的话会自动启动通过类型装配。**
- @Autowired注解默认根据类型装配,如果想根据名称装配,需要配合@Qualifier注解一起用。
- @Resource注解用在属性上、setter方法上。
- @Autowired注解用在属性上、setter方法上、构造方法上、构造方法参数上。

总结:

(1)@Autowired注解默认根据类型装配,如果类型没有,则报错。如果想根据名称装配,需要配合@Qualifier注解一起用。一旦使用名称来装配,即使类型有,但是名称不匹配也会报错。

(2)@Resource注解默认根据Bean名称装配,如果Bean名称找不到,则会启动根据类型来装配。如果指定了名称,类型有但是名称不匹配就会报错。如果没有启动名称匹配,则后续会在进行类型匹配。

4、使用@Value注解

对于基本数据类型的DI

对于基本数据类型

我们可以直接赋值的方式

比如

private int age=8;

同时我们也可以使用@Value注解 这个注解主要是为了配置外部属性

a.配置组件

package demo04;@Service 
public class JavaBean 
{ private int age=8; 
 @Value("${url}") 
private String url; 
 @Value("${a:cui}") 冒号后边是默认值,即配置中如果没有a属性的话,就自动赋值为冒号后边的值。 
private String name;@Override public String toString() 
{ return "JavaBean{" + "age=" + age + ", url='" + url + '\'' + ", name='" + name + '\'' + '}'; } }

b. 配置信息 demo04.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:context=""xsi:schemaLocation=" .xsd  .xsd">
// 扫描的包
<context:component-scan base-package="demo04">
</context:component-scan>
//把配置的包导入进来,之后在该容器中的组件都可以通过{$xxx}来访问xxx属性名的值
<context:property-placeholder location="aoo.properties"></context:property-placeholder>
</beans>

c.一些外部配置文件 aoo,properties

 5、总结:

基于注解的方式,我们还是需要xml配置文件

xml配置:①扫描包的配置 ②外部配置包的部署 ③第三方组件 如jdbctemplate等

之后我们将学习配置类的方式,使用上配置类我们就可以不用在使用xml的方式来完成上边三种配置了。

更多推荐

SpringFrameWork之注解类管理Bean

本文发布于:2023-12-07 11:41:53,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1671130.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:注解   SpringFrameWork   Bean

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!