Spring IOC(注解方式)

简介: Spring IOC(注解方式)

IOC(注解方式)

注解:是代码特殊标记,可以作用在类、方法、属性上,使用注解可以简化xml配置

格式@注解名称(属性名称 =属性值, 属性名称 =属性值....)

使用注解方式管理Bean需要引入相关依赖

用于创建对象的注解

相当于xml文件中的<bean id="" class="">

注解 描述
@Component 作用: 把资源让 spring 来管理。相当于在 xml 中配置一个 bean。
属性value:指定 bean 的 id。如果不指定 value 属性,默认 bean 的 id 是当前类首字母小写的类名
@Controller 一般用于表现层的注解,作用与属性和@Component相同
@Service 一般用于业务层的注解,作用与属性和@Component相同
@Repository 一般用于持久层的注解,作用与属性和@Component相同

上面四个注解功能是一样的,都可以用来创建bean的实例 如果注解中有且只有一个属性要赋值时,且名称是 value,则 value 在赋值是可以不写。

快速入门

使用注解需要先开启组件扫描,需要用到spring中xmlns:context的约束

<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">

    <!-- 
    开启组件扫描
    base-package="run.arbor.spring5demo4":配置需要扫描的包        
     -->
    <context:component-scan base-package="run.arbor.spring5demo4"/>
</beans>

开启组件扫描后,创建类,并且在类上添加创建对象的注解

@Component(value = "userService")
public class UserService {
   
   
    public void add() {
   
   
        System.out.println("service add....");
    }
}

这里的@Component(value = "userService")相当于xml形式的

<bean id="userService" class="..."/>

value属性可以省略不写,不写的话默认设置id为首字母小写的当前类名,比如UserService则默认为userService

@Component也可以变更为其他三个注解,因为效果是一样的,四种不同的注解可以做区分效果,比如Service层的类可以使用@Service注解,Dao层的类可已使用@Repository注解

@Test
public void testService() {
   
   
    ApplicationContext context = new ClassPathXmlApplicationContext("bean4_1.xml");
    UserService userService = context.getBean("userService", UserService.class);
    userService.add();
}

通过上面的测试方法可以得到以下结果,说明注解方式使用成功

image

context:component-scan标签

设置扫描的包

开启组件扫描设置扫描的包有两种方法

  1. 如果需要扫描多个包,可以使用逗号隔开

这里扫描的就是run.arbor.spring5demo4中的dao包和service包

<context:component-scan base-package="run.arbor.spring5demo4.dao,run.arbor.spring5demo4.service"/>
  1. 需要扫描包的上层目录

这里扫描的就是run.arbor.spring5demo4中的类和所有子包中的类

<context:component-scan base-package="run.arbor.spring5demo4"/>

设置扫描的内容

如果想扫描run.arbor.spring5demo4包中所有带@Controller的类,不想扫描带@Service或者其他两个注解的类,可以使用filter来完成相关功能

  • use-default-filters="false":不使用默认的filter,自定义filter
  • <context:include-filter>:设置扫描哪些内容
    • type="annotation":扫描注解
    • expression="org.springframework.stereotype.Controller":扫描使用Controller注解的类

设置不扫描的内容

如果想扫描run.arbor.spring5demo4包中所有除了带@Controller的类,可以使用<context:exclude-filter>标签

  • <context:exclude-filter>:设置不扫描哪些内容
    • type="annotation":扫描注解
    • expression="org.springframework.stereotype.Controller":不扫描使用Controller注解的类

用于注入属性的注解

相当于xml文件的:<property name="" ref=""><property name="" value="">

注解 描述
@Autowired 自动按照类型注入。 只能注入其他 bean 类型,set 方法可以省略。当有多个类型匹配时,需要使用@Qualifier注解来指定 bean 的 id。
@Qualifier 作用:在自动按照类型注入的基础之上,再按照 Bean 的 id 注入。它在给字段注入时不能独立使用,必须和 @Autowired 一起使用;但是给方法参数注入时,可以独立使用。
属性value:指定 bean 的 id。
@Resource 作用: 直接按照 Bean 的 id 注入。它也只能注入其他 bean 类型。
属性name:指定 bean 的 id。
@Value 作用: 注入基本数据类型和 String 类型数据的属性
属性value:用于指定值

使用@Autowired@Qualifier注解

创建dao对象

// value可以自定义对象的名字
@Repository(value = "userDaoImpl")
public class UserDaoImpl implements UserDao{
   
   
    @Override
    public void add() {
   
   
        System.out.println("dao add...");
    }
}

如果UserDao有多个实现类的话,必须使用@Qualifier来确定注入的是哪个对象,如果只有一个实现类那么写不写 @Qualifier 都可以,如果写的话,value属性必须和UserDao对象创建时的value值相同,比如:@Repository(value = "userDaoImpl111"),那么就必须是 @Qualifier(value = "userDaoImpl111")

@Component(value = "userService")
public class UserService {
   
   

    // 使用@Autowired注解,定义UserDao类型的属性,可以不用set方法
    @Autowired
    @Qualifier(value = "userDaoImpl")  // 根据名称注入
    private UserDao userDao;

    public void add() {
   
   
        System.out.println("service add...");
        userDao.add();
    }
}

使用@Resource注解

因为@Resource注解是Java的拓展包,不是Spring官方提供的,所以更建议使用上面两个注解

如果UserDao有多个实现类的话,必须使用name属性值来确定注入的是哪个对象,如果只有一个实现类那么写不写name都可以

@Component(value = "userService")
public class UserService {
   
   

//    @Resource   // 根据类型注入
    @Resource(name = "userDaoImpl1")    // 根据名称注入
    private UserDao userDao;

    public void add() {
   
   
        System.out.println("service add...");
        userDao.add();
    }
}

使用@Value注解

注入基本数据类型和 String 类型数据的属性

@Component(value = "userService")
public class UserService {
   
   

    @Resource(name = "userDaoImpl1")
    private UserDao userDao;

    @Value(value = "abc")   // 基本类型注入和String类型注入
    private String name;

    public void add() {
   
   
        System.out.println("service add...");
        System.out.println(name);
        userDao.add();
    }
}

也可以通过spring的表达式获取配置文件中的值,可以看本文的 3.2 小节的第二步代码演示

@Scope用于改变Bean作用范围的注解

相当于:<bean id="" class="" scope="">scope=""

作用: 指定 bean 的作用范围。

属性value:指定范围的值。

value取值:

描述
singleton 默认值,单例的
prototype 多例的
request WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中
session WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中
globalsession WEB 项目中,应用在 Portlet 环境。如果没有 Portlet 环境那么globalSession 相当于 session

和Bean生命周期相关的注解

相当于:<bean id="" class="" init-method="" destroy-method="" >init-method="" destroy-method=""

注解 描述
@PostConstruct 用于指定初始化方法
@PreDestroy 用于指定销毁方法

完全使用注解开发

在上面的代码中,使用注解需要先在xml文件中开启组件扫描,这样还是需要配置文件,这一步也可以使用注解配置

注解 描述
@Configuration 作用: 指定当前类是一个 spring 配置类,当创建容器时会从该类上加载注解。获取容器时需要使用AnnotationConfigApplicationContext(有@Configuration 注解的类.class)。
属性value:用于指定配置类的字节码
@ComponentScan 作用: 用于指定 spring 在初始化容器时要扫描的包。作用和xml配置文件中的:<context:component-scan base-package="run.arbor"/> 是一样的。
属性
basePackages:用于指定要扫描的包。
value:和basePackages的属性作用一样,可以是一个字符串数组
excludeFilters :设置扫描加载bean时,排除的过滤规则,需要指定类别(type)和具体项(classes)
includeFilters:加载指定的bean,需要指定类别(type)和具体项(classes)
@Bean 作用: 该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器。
属性name:给当前@Bean注解方法创建的对象指定一个名称(即 bean 的 id)。
@PropertySource 作用: 用于加载 .properties文件中的配置。例如配置数据源时,可以把连接数据库的信息写到 properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。
属性value[]:用于指定 properties 文件位置。如果是在类路径下,需要写上classpath:
@Import 作用: 用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration 注解,写上也没问题。
属性value[]:用于指定其他配置类的字节码。

使用@Configuration@ComponentScan注解

第一步: 创建配置类,用于替代xml配置文件,类名随意
工作中一般会创建一个config包用于放配置类

@Configuration  // 告诉spring这是一个配置类
@ComponentScan(basePackages = {
   
   "run.arbor"})  // 用于指定 spring 在初始化容器时要扫描的包。
// 相当于xml文件的:<context:component-scan base-package="run.arbor"/>
public class SpringConfig {
   
   
}

第二步: 此时再使用Spring创建的对象的时候,需要使用AnnotationConfigApplicationContext来获取,而参数中应该传入刚刚写的添加了@Configuration@ComponentScan注解的类

@Test
public void testService() {
   
   
    // 使用AnnotationConfigApplicationContext
    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    UserService userService = context.getBean("userService", UserService.class);
    userService.add();
}

@ComponentScan 注解过滤

设置扫描加载bean时,排除过滤的规则

  • type属性:设置排除规则,当前使用按照bean定义时的注解类型进行排除
    • ANNOTATION:按照注解排除(只知道这种即可)
    • ASSIGNABLE_TYPE:按照指定的类型过滤
    • ASPECTJ:按照Aspectj表达式排除,基本上不会用
    • REGEX:按照正则表达式排除
    • CUSTOM:按照自定义规则排除
  • classes属性:设置排除的具体注解类,当前设置排除@Controller定义的bean
@Configuration
@ComponentScan(value="com.qaomuu",
    excludeFilters=@ComponentScan.Filter(
        type = FilterType.ANNOTATION,
        classes = Controller.class
    )
)
public class SpringConfig {
   
   
}

使用@PropertySource@Bean注解

第一步: 比如我们要配置一个数据源,可以在src目录下写一个jdbc.properties文件:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/day44_ee247_spring
jdbc.username=root
jdbc.password=1234

第二步: 创建一个配置类

@Configuration
@PropertySource("classpath:jdbc.properties")    // 因为在src目录下,可以使用classpath:写相对路径
public class JdbcConfig{
   
   

    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    /**
    * 创建一个数据源,并存入 spring 容器中
    * @Bean:创建一个数据源对象
    * name:该对象的名字
    * 该方法的返回值就是创建的对象的类型
    */
    @Bean(name="dataSource")
    public DataSource createDataSource() {
   
   
        try {
   
   
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driver);
            ds.setJdbcUrl(url);
            ds.setUser(username);
            ds.setPassword(password);
            return ds;
        } catch (Exception e) {
   
   
            throw new RuntimeException(e);
        }
    }

    /**
    * 创建一个 DBAssit,并且也存入 spring 容器中
    */
    @Bean(name="dbAssit")
    public DBAssit createDBAssit(DataSource dataSource) {
   
   
        return new DBAssit(dataSource);
    }
}

使用@Import注解

在上一小节的基础上,使用@Import注解将刚刚创建的配置类引入

@Configuration
@ComponentScan(basePackages = "run.arbor.spring")
@Import({
   
   JdbcConfig.class})    // 将刚刚创建的配置类引入
public class SpringConfiguration {
   
   
}

此时可以在测试方法中,通过SpringConfiguration类(↑这个类)来创建对象。

ApplicationContext ac = 
new AnnotationConfigApplicationContext(SpringConfiguration.class);

配置类和配置文件可以写在类路径下的任意位置

注解和 XML 的选择

注解的优势:配置简单,维护方便(找到类,就相当于找到了对应的配置)。

XML 的优势:修改时,不用改源码。不涉及重新编译和部署。

基于注解的 Spring IOC 配置中,bean 对象的特点和基于 XML 配置是一模一样的。

Spring 管理 Bean 方式的比较

基于XML配置 基于注解配置
Bean定义 <bean id="..." class="..."/> @Component衍生类 @Repository@Service@Controller
Bean名称 通过id或name执行 @Component("这里指定")
Bean注入 <property>或者p命名空间 @Autowired 按类型注入@Qualifier按名称注入
生命过程
Bean作用范围
init-methoddestroy-method;范围scope属性 @PostConstruct初始化@PreDestroy销毁@Scope设置作用范围
适用场景 Bean来自第三方 Bean的实现类由自己开发(工作中常用)
目录
相关文章
|
2月前
|
Java 开发者 Spring
【SpringBoot 异步魔法】@Async 注解:揭秘 SpringBoot 中异步方法的终极奥秘!
【8月更文挑战第25天】异步编程对于提升软件应用的性能至关重要,尤其是在高并发环境下。Spring Boot 通过 `@Async` 注解简化了异步方法的实现。本文详细介绍了 `@Async` 的基本用法及配置步骤,并提供了示例代码展示如何在 Spring Boot 项目中创建与管理异步任务,包括自定义线程池、使用 `CompletableFuture` 处理结果及异常情况,帮助开发者更好地理解和运用这一关键特性。
125 1
|
2月前
|
XML Java 测试技术
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
这篇文章介绍了Spring5框架的三个新特性:支持@Nullable注解以明确方法返回、参数和属性值可以为空;引入函数式风格的GenericApplicationContext进行对象注册和管理;以及如何整合JUnit5进行单元测试,同时讨论了JUnit4与JUnit5的整合方法,并提出了关于配置文件加载的疑问。
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
|
2月前
|
缓存 Java 数据库连接
Spring Boot奇迹时刻:@PostConstruct注解如何成为应用初始化的关键先生?
【8月更文挑战第29天】作为一名Java开发工程师,我一直对Spring Boot的便捷性和灵活性着迷。本文将深入探讨@PostConstruct注解在Spring Boot中的应用场景,展示其在资源加载、数据初始化及第三方库初始化等方面的作用。
53 0
|
21天前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
119 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
9天前
|
XML Java 测试技术
spring复习01,IOC的思想和第一个spring程序helloWorld
Spring框架中IOC(控制反转)的思想和实现,通过一个简单的例子展示了如何通过IOC容器管理对象依赖,从而提高代码的灵活性和可维护性。
spring复习01,IOC的思想和第一个spring程序helloWorld
|
1天前
|
缓存 NoSQL Java
Springboot自定义注解+aop实现redis自动清除缓存功能
通过上述步骤,我们不仅实现了一个高度灵活的缓存管理机制,还保证了代码的整洁与可维护性。自定义注解与AOP的结合,让缓存清除逻辑与业务逻辑分离,便于未来的扩展和修改。这种设计模式非常适合需要频繁更新缓存的应用场景,大大提高了开发效率和系统的响应速度。
8 2
|
6天前
|
缓存 Java Spring
手写Spring Ioc 循环依赖底层源码剖析
在Spring框架中,IoC(控制反转)是一个核心特性,它通过依赖注入(DI)实现了对象间的解耦。然而,在实际开发中,循环依赖是一个常见的问题。
15 4
|
10天前
|
XML Java 开发者
经典面试---spring IOC容器的核心实现原理
作为一名拥有十年研发经验的工程师,对Spring框架尤其是其IOC(Inversion of Control,控制反转)容器的核心实现原理有着深入的理解。
31 3
|
10天前
|
Java Spring 容器
Spring使用异步注解@Async正确姿势
Spring使用异步注解@Async正确姿势,异步任务,spring boot
|
9天前
|
XML Java 数据格式
spring复习03,注解配置管理bean
Spring框架中使用注解配置管理bean的方法,包括常用注解的标识组件、扫描组件、基于注解的自动装配以及使用注解后的注意事项,并提供了一个基于注解自动装配的完整示例。
spring复习03,注解配置管理bean
下一篇
无影云桌面