【Spring】Spring IoC 注解式开发

一、回顾注解

注解的存在主要是为了简化XML的配置

Spring6倡导全注解开发

我们来回顾一下:

  • 第一:注解怎么定义,注解中的属性怎么定义?

  • 第二:注解怎么使用?

  • 第三:通过反射机制怎么读取注解?

package com.qiu.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package com.qiu.annotation
 * @date 2022-11-13-17:20
 * @since 1.0
 *
 * @Target 标注注解的注解,元注解,用于定注解可以出现的位置
 *
 * @Target(value = {ElementType.TYPE,ElementType.FIELD}) 表示:
 * Component 注解可以出现在类上、属性上
 *
 * 使用某个注解的时候,注解的属性名是 value 的话,value 可以省略
 * @Target({ElementType.TYPE,ElementType.FIELD})
 * 使用某个注解的时候,注解的属性值是 数组 的话,且只有一个元素,大括号可以省略
 * @Target(ElementType.TYPE)
 *
 * @Retention(RetentionPolicy.SOURCE)
 * @Retention 也是一个元注解,用来标注 @Component 注解最终保留的位置
 */
@Target(value = {ElementType.TYPE,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
    String value();
    
}

用法简单,语法格式:@注解类型名(属性名=属性值, 属性名=属性值, 属性名=属性值......)

userBean 为什么使用双引号括起来,因为 value 属性是 String 类型,字符串

另外如果属性名是 value,则在使用的时候可以省略属性名,例如:

//@Component(value = "userBean")
@Component("userBean")
class User{
}

通过反射机制怎么读取注解?

接下来,我们来写一段程序,当 Bean 类上有 Component 注解时,则实例化 Bean 对象,如果没有,则不实例化对象

我们准备两个Bean,一个上面有注解,一个上面没有注解

package com.qiu.bean;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package com.qiu.annotation
 * @date 2022-11-13-17:36
 * @since 1.0
 */
@Component("userBean")
public class User {
}
package com.qiu.bean;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package com.qiu.annotation
 * @date 2022-11-13-17:37
 * @since 1.0
 */
public class Vip {
}

假设我们现在只知道包名,至于这个包下有多少个Bean我们不知道;哪些Bean上有注解,哪些Bean上没有注解,这些我们都不知道,如何通过程序全自动化判断  

package com.qiu.annotation;

import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package com.qiu.annotation
 * @date 2022-11-13-17:39
 * @since 1.0
 */
public class Test {
    public static void main(String[] args) {
        Map<String,Object> beanMap = new HashMap<>();

        String packageName = "com.qiu.bean";
        // String packagePath = packageName.replaceAll("\\.","/");
        String packagePath = packageName.replace(".","/");

        URL url = ClassLoader.getSystemClassLoader().getResource(packagePath);
        String path = url.getPath();
        // System.out.println(path);
        File file = new File(path);
        File[] files = file.listFiles();
        Arrays.stream(files).forEach(f -> {
            // System.out.println(f.getName().split("\\.")[0]);
            String className = packageName + "." + f.getName().split("\\.")[0];

            // 反射机制解析注解
            Class<?> aClass = null;
            try {
                aClass = Class.forName(className);
                if (aClass.isAnnotationPresent(Component.class)) {
                    // 获取注解
                    Component component = aClass.getAnnotation(Component.class);
                    String id = component.value();
                    // 创建对象
                    Object o = aClass.newInstance();
                    beanMap.put(id, o);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        System.out.println(beanMap);
    }
}

运行结果:  

 

二、声明 Bean 的注解

负责声明 Bean 的注解,常见的包括四个:

  • @Component

  • @Controller

  • @Service

  • @Repository

@Component 注解源码:

package org.springframework.stereotype;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

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

@Controller 源码:  

package org.springframework.stereotype;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;

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

@Service 源码:  

 

package org.springframework.stereotype;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;

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

@Repository 源码:  

package org.springframework.stereotype;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;

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

通过源码可以看到,@Controller、@Service、@Repository 这三个注解都是 @Component 注解的别名

也就是说:这四个注解的功能都一样。用哪个都可以

只是为了增强程序的可读性,建议:

  • 控制器类上使用:Controller

  • service 类上使用:Service

  • dao 类上使用:Repository

他们都是只有一个 value 属性。value 属性用来指定bean 的 id,也就是 bean 的名字

 

三、Spring 注解的使用

如何使用以上的注解呢?

  • 第一步:加入aop的依赖

  • 第二步:在配置文件中添加context命名空间

  • 第三步:在配置文件中指定扫描的包

  • 第四步:在Bean类上使用注解

第一步:加入aop的依赖

我们可以看到当加入 spring-context 依赖之后,会关联加入 aop 的依赖,所以这一步不用做

第二步:在配置文件中添加context命名空间  

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

第三步:在配置文件中指定要扫描的包  

<!-- 指定要扫描的包 -->
<context:component-scan base-package="org.qiu.spring.bean"/>

第四步:在Bean类上使用注解  

package org.qiu.spring.bean;

import org.springframework.stereotype.Component;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package org.qiu.spring.bean
 * @date 2022-11-13-22:40
 * @since 1.0
 */
@Component(value = "userBean")
public class User {
}
@Test
public void testBean(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    User userBean = applicationContext.getBean("userBean", User.class);
    System.out.println(userBean);
}

运行结果: 

如果注解的属性名是value,那么value是可以省略的

如果把value属性彻底去掉,spring会给Bean自动取名,默认名字的规律是:Bean类名首字母小写即可

如果是多个包怎么办?有两种解决方案:

  • 第一种:在配置文件中指定多个包,用逗号隔开

  • 第二种:指定多个包的共同父包

方案一:在配置文件中指定多个包

<!-- 指定要扫描的包 -->
<context:component-scan base-package="org.qiu.spring.bean,org.qiu.spring.dao"/>
package org.qiu.spring.dao;

import org.springframework.stereotype.Component;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package org.qiu.spring.dao
 * @date 2022-11-14-07:49
 * @since 1.0
 */
@Component("userDao")
public class UserDao {
}
@Test
public void testBean(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    User userBean = applicationContext.getBean("userBean", User.class);
    System.out.println(userBean);

    UserDao userDao = applicationContext.getBean("userDao", UserDao.class);
    System.out.println(userDao);
}

运行结果:

方案二:指定共同的父包  

<!-- 指定要扫描的包 -->
<context:component-scan base-package="org.qiu.spring"/>

运行效果:  

 

四、选择性实例化 Bean

假设在某个包下有很多Bean,有的Bean上标注了Component,有的标注了Controller,有的标注了Service,有的标注了Repository,现在由于某种特殊业务的需要,只允许其中所有的Controller参与Bean管理,其他的都不实例化,应该怎么办呢?  

package org.qiu.spring.bean2;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package org.qiu.spring.bean2
 * @date 2022-11-14-07:57
 * @since 1.0
 */

@Component
public class A {
    public A() {
        System.out.println("A");
    }
}

@Controller
class B {
    public B() {
        System.out.println("B");
    }
}

@Service
class C {
    public C() {
        System.out.println("C");
    }
}

@Repository
class D {
    public D() {
        System.out.println("D");
    }
}

@Controller
class E {
    public E() {
        System.out.println("E");
    }
}
@Test
public void testChoose(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-choose.xml");
}

默认情况下:  

<context:component-scan base-package="org.qiu.spring.bean2" />

运行结果:

选择性实例化Bean:

方式一:

<context:component-scan base-package="org.qiu.spring.bean2"  use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

use-default-filters="true" 表示:

使用spring默认的规则,只要有Component、Controller、Service、Repository中的任意一个注解标注,则进行实例化

use-default-filters="false" 表示:

不再spring默认实例化规则,即使有Component、Controller、Service、Repository这些注解标注,也不再实例化

<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> 表示只有Controller进行实例化

 运行效果:

方式二:

也可以将use-default-filters设置为true(不写就是true),并且采用exclude-filter方式排出哪些注解标注的Bean不参与实例化:

<context:component-scan base-package="org.qiu.spring.bean2">
  <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属性赋值需要用到这些注解:

  • @Value

  • @Autowired

  • @Qualifier

  • @Resource

@Value

当属性的类型是简单类型时,可以使用@Value注解进行注入

使用 @Value 注解,可以不写 setter 方法

@Value注解可以出现在属性上、setter 方法上、以及构造方法的形参上

为了简化代码,以后我们一般不提供 setter 方法,直接在属性上使用 @Value 注解完成属性赋值

package org.qiu.spring.bean3;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package org.qiu.spring.bean3
 * @date 2022-11-14-11:25
 * @since 1.0
 */
@Component
public class MyDataSource implements DataSource {

    @Value("com.mysql.cj.jdbc.Driver")
    private String driver;
    @Value("jdbc:mysql://localhost:3306/spring")
    private String url;
    @Value("root")
    private String username;
    @Value("mysql")
    private String password;

    @Override
    public String toString() {
        return "MyDataSource{" +
                "driver='" + driver + '\'' +
                ", url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    // 省略实现 DataSource 接口的方法
}
<?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="org.qiu.spring.bean3"/>

</beans>
@Test
public void testDIByAnnotation(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-di-annotation.xml");
    MyDataSource myDataSource = applicationContext.getBean("myDataSource", MyDataSource.class);
    System.out.println(myDataSource);
}

运行效果:  

 

@Autowired 和 @Qualifier

@Autowired 注解可以用来注入非简单类型

单独使用 @Autowired 注解,默认根据类型装配【默认是byType】

@Autowired 源码:

package org.springframework.beans.factory.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
	boolean required() default true;
}

源码中有两处需要注意:

  • 第一处:该注解可以标注在哪里?

  • 构造方法上

    • 方法上

    • 形参上

    • 属性上

    • 注解上

  • 第二处:该注解有一个 required 属性,默认值是 true,表示在注入的时候要求被注入的 Bean 必须是存在的,如果不存在则报错。如果 required 属性设置为 false,表示注入的 Bean 存在或者不存在都没关系,存在的话就注入,不存在的话,也不报错

package com.qiu.dao;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package com.qiu.dao
 * @date 2022-11-14-22:09
 * @since 1.0
 */
public interface OrderDao {
    void insert();
}
package com.qiu.dao.impl;

import com.qiu.dao.OrderDao;
import org.springframework.stereotype.Repository;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package com.qiu.dao.impl
 * @date 2022-11-14-22:09
 * @since 1.0
 */
@Repository
public class OrderDaoImplForMySql implements OrderDao {
    @Override
    public void insert() {
        System.out.println("MySql 数据库正在保存订单信息......");
    }
}
package com.qiu.service;

import com.qiu.dao.OrderDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package com.qiu.service
 * @date 2022-11-14-22:10
 * @since 1.0
 */
@Service
public class OrderService {

    // @Autowired 使用时不需要指定任何属性,直接使用即可【根据类型 byType 进行自动装配】
    @Autowired
    private OrderDao orderDao;

    public void generate(){
        orderDao.insert();
    }
}
<?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
       https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.qiu"/>

</beans>
@Test
public void testAutowired(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-autowired.xml");
    OrderService orderService = applicationContext.getBean("orderService", OrderService.class);
    orderService.generate();
}

运行结果:  

以上构造方法和 setter 方法都没有提供,经过测试,仍然可以注入成功

@Autowired 注解 可以出现在 setter 方法上、构造方法上

而且当参数的构造方法只有一个的时候,@Autowired 注解可以省略(如果有多个时不能省略)

@Autowired 注解默认是 byType 进行注入的,也就是说根据类型注入的,如果以上程序中,OrderDao接口还有另外一个实现类

当你写完这个新的实现类之后,此时IDEA工具已经提示错误信息了:

怎么解决这个问题呢?当然要byName,根据名称进行装配了

@Autowired 注解和 @Qualifier 注解联合起来才可以根据名称进行装配,在 @Qualifier 注解中指定 Bean 名称

package com.qiu.dao.impl;

import com.qiu.dao.OrderDao;
import org.springframework.stereotype.Repository;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package com.qiu.dao.impl
 * @date 2022-11-14-22:23
 * @since 1.0
 */
@Repository // 这里没有给 bean 起名字,默认为 orderDaoImplOracle
public class OrderDaoImplOracle implements OrderDao {
    @Override
    public void insert() {
        System.out.println("Oracle 数据库正在保存订单信息......");
    }
}
package com.qiu.service;

import com.qiu.dao.OrderDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package com.qiu.service
 * @date 2022-11-14-22:10
 * @since 1.0
 */
@Service
public class OrderService {

    @Autowired
    @Qualifier("orderDaoImplForOracle")
    private OrderDao orderDao;

    public void generate(){
        orderDao.insert();
    }
}
@Test
public void testAutowired(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-autowired.xml");
    OrderService orderService = applicationContext.getBean("orderService", OrderService.class);
    orderService.generate();
}

运行结果: 

总结:

  • @Autowired注解可以出现在:属性上、构造方法上、构造方法的参数上、setter方法上

  • 当带参数的构造方法只有一个,@Autowired注解可以省略

  • @Autowired注解默认根据类型注入。如果要根据名称注入的话,需要配合@Qualifier注解一起使用

@Resource

@Resource注解也可以完成非简单类型注入。那它和 @Autowired 注解有什么区别?

  • @Resource 注解是 JDK 扩展包中的,也就是说属于 JDK 的一部分,所以该注解是标准注解,更加具有通用性 (JSR-250 标准中制定的注解类型,JSR 是 Java 规范提案)

  • @Autowired 注解是 Spring 框架自己的

  • @Resource 注解默认根据名称装配 byName,未指定 name 时,使用属性名作为 name,通过 name 找不到的话会自动启动通过类型 byType 装配

  • @Autowired 注解默认根据类型装配 byType,如果想根据名称装配,需要配合 @Qualifier 注解一起用

  • @Resource 注解用在属性上、setter 方法上

  • @Autowired 注解用在属性上、setter 方法上、构造方法上、构造方法参数上

@Resource 注解属于 JDK 扩展包,所以不在 JDK 当中,需要额外引入以下依赖:【如果是 JDK8 的话不需要额外引入依赖高于 JDK11 或低于 JDK8 需要引入以下依赖】

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

一定要注意:如果你用 Spring6,要知道 Spring6 不再支持 JavaEE,它支持的是 JakartaEE9

Oracle 把 JavaEE 贡献给 Apache了,Apache 把 JavaEE 的名字改成 JakartaEE 了,大家之前所接触的所有的 javax.* 包名统一修改为 jakarta.* 包名了

<dependency>
  <groupId>javax.annotation</groupId>
  <artifactId>javax.annotation-api</artifactId>
  <version>1.3.2</version>
</dependency>

@Resource注解的源码如下:  

package cn.qiu.dao;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package cn.qiu.dao
 * @date 2022-11-15-09:19
 * @since 1.0
 */
public interface StudentDao {
    void deleteById();
}
package cn.qiu.dao.impl;

import cn.qiu.dao.StudentDao;
import org.springframework.stereotype.Repository;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package cn.qiu.dao.impl
 * @date 2022-11-15-09:19
 * @since 1.0
 */
@Repository
public class StudentDaoImplForMySql implements StudentDao {
    @Override
    public void deleteById() {
        System.out.println("MySQL 数据库正在删除学生信息......");
    }
}
package cn.qiu.service;

import cn.qiu.dao.StudentDao;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package cn.qiu.service
 * @date 2022-11-15-09:20
 * @since 1.0
 */
@Service
public class StudentService {
    @Resource(name = "studentDaoImplForMySql")
    private StudentDao studentDao;

    public void deleteStudent(){
        studentDao.deleteById();
    }
}
<?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="cn.qiu"/>

</beans>
@Test
public void testResource(){
    ApplicationContext application = new ClassPathXmlApplicationContext("spring-resource.xml");
    StudentService studentService = application.getBean("studentService", StudentService.class);
    studentService.deleteStudent();
}

运行结果:  

当 @Resource 注解使用时没有指定 name 的时候,还是根据 name 进行查找,这个 name 是属性名

当通过 name 找不到的时候,自然会启动 byType 进行注入,此时若 StudentDao 接口有多个实现类,就会报错

package cn.qiu.service;

import cn.qiu.dao.StudentDao;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package cn.qiu.service
 * @date 2022-11-15-09:20
 * @since 1.0
 */
@Service
public class StudentService {
    @Resource
    private StudentDao studentDao2;

    public void deleteStudent(){
        studentDao2.deleteById();
    }
}
package cn.qiu.dao.impl;

import cn.qiu.dao.StudentDao;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package cn.qiu.dao.impl
 * @date 2022-11-15-09:30
 * @since 1.0
 */
@Repository
public class StudentDaoImplForOracle implements StudentDao {
    @Override
    public void deleteById() {
        System.out.println("Oracle 数据库正在删除学生信息......");
    }
}

 

六、全注解开发 

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

package cn.qiu;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author 秋玄
 * @version 1.0
 * @email qiu_2022@aliyun.com
 * @project Spring
 * @package cn.qiu
 * @date 2022-11-15-09:38
 * @since 1.0
 */
@Configuration
@ComponentScan({"cn.qiu.dao","cn.qiu.service"})
public class SpringConfig {
}
@Test
public void testNoXML(){
    ApplicationContext application = new AnnotationConfigApplicationContext(SpringConfig.class);
    StudentService studentService = application.getBean("studentService", StudentService.class);
    studentService.deleteStudent();
}

运行结果:  

 

一  叶  知  秋,奥  妙  玄  心

相关推荐

  1. 注解开发Spring

    2024-03-26 07:42:12       13 阅读
  2. 【spring6】Spring IoC注解开发

    2024-03-26 07:42:12       23 阅读
  3. Spring之注解开发

    2024-03-26 07:42:12       36 阅读
  4. Spring-注解开发

    2024-03-26 07:42:12       39 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-26 07:42:12       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-26 07:42:12       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-26 07:42:12       20 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-26 07:42:12       20 阅读

热门阅读

  1. 开发指南018-前端存储

    2024-03-26 07:42:12       16 阅读
  2. 关于HDP的20道高级运维面试题

    2024-03-26 07:42:12       17 阅读
  3. vite的import.meta.glob的用法

    2024-03-26 07:42:12       17 阅读
  4. hadoop 常用命令

    2024-03-26 07:42:12       16 阅读
  5. Swagger

    Swagger

    2024-03-26 07:42:12      18 阅读
  6. ARM I2C温湿度实验

    2024-03-26 07:42:12       15 阅读
  7. 【链表】Leetcode 146. LRU 缓存【中等】

    2024-03-26 07:42:12       18 阅读