Spring系列基于Annotation(注解)的装配应用

Posted 一宿君

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring系列基于Annotation(注解)的装配应用相关的知识,希望对你有一定的参考价值。

6 基于Annotation(注解)的装配方式实现数据库操作

在Spring中,尽管使用XML配置文件可以实现Bean的装配工作,但如果应用中有很多Bean时也有很多增强事务通知时会到值XMl配置文件过于臃肿,不利于后续的升级维护和扩展,因此,Spring就根据这种情况提供了基于Annotation注解技术的全面支持

Spring中常用的注解方法:

注解名称注解描述
@Component描述Spring中的Bean,是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次,使用时只需将该注解标注在相应类上即可。
@Repository用于将数据访问层(Dao层)的实现类标识为Spring中的Bean,其功能与@Component相同
@Service用于将业务层(Service层)的实现类标识为Spring中的Bean,其功能与@Component相同
@Controller用于将控制层(Controller层)的类标识为Spring中的Bean,其功能与@Component相同
@Autowired用于对Bean的属性变量、属性的setter方法以及构造方法进行标注,配合对应的注解处理器完成Bean的自动装配工作,默认按照Bean的类型进行装配。
@Qualifier与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean实例名称装配,Bean的实例名称由@Qualifier的参数指定
@Resource其作用与Autowired一样。其区别在于@Autowired默认按照Bean类型装配,而@Resource默认按照Bean实例名称进行装配
@Aspect一般作用在一个共用模块类上,该模块中有多个影响类的公共行为,我们称之为切面,该注解的作用就是把当前的切面类标识为一个切面共容易读取
@PointcutPointcut是织入Advice的触发条件,每个Pointcut的定义包括2两部分,一是:表达式;二是:方法签名。方法签名必须是public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码
@Around环绕增强,相当于MethodInterceptor
@Before前置增强,相当于BeforeAdvice的功能
@AfterReturning后置增强,想当于AfterReturningAdvice,方法正常退出时执行
@AfterThrowing异常抛出增强,相当于ThrowsAdvice
@Afterfinal最终增强,不管是抛出异常还是正常退出都会执行

@Resource中有两个重要属性:name和type。
Spring将name解析为Bean实例名称,type属性解析为Bean实例类型。
如果指定name属性,则按Bean实例名称进行装配;
如果指定type属性,则按照Bean类型进行装配;
如果都不指定,则先按照Bean实例名称装配;
如果不能匹配,再按照Bean类型进行装配;
如果都无法匹配,则抛出NoSuchBeanDefinitionException异常。
@Autowired和@Qualifier配合使用与@Resource作用相同,处于注解的简化思想,推荐使用@Resource注解,直接指定name属性或者type属性值

直接上代码演示实例,新建maven项目SpringDemo
在这里插入图片描述

  • 第一步首选配置maven依赖

        <!--spring上下文依赖(包含spring的所有常用的aop、core、bean、context标签包依赖)-->
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>5.2.3.RELEASE</version>
        </dependency>
    
        <!--log4j日志文件-->
        <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>1.2.17</version>
        </dependency>
        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
          <version>1.7.21</version>
        </dependency>
        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
          <version>1.7.21</version>
        </dependency>
    
        
        <!--javaee-api中含有mail邮件api-->
        <dependency>
          <groupId>javax</groupId>
          <artifactId>javaee-api</artifactId>
          <version>8.0</version>
        </dependency>
    
  • log4j.properties日志记录记录文件

    # rootLogger是所有日志的根日志,修改该日志属性将对所有日志起作用
    # 下面的属性配置中,所有日志的输出级别是info,输出源是con
    log4j.rootLogger=debug,con
    # 定义输出源的输出位置是控制台
    log4j.appender.con=org.apache.log4j.ConsoleAppender
    # 定义输出日志的布局采用的类
    log4j.appender.con.layout=org.apache.log4j.PatternLayout
    # 定义日志输出布局
    log4j.appender.con.layout.ConversionPattern=[%p] %d %c - %m%n
    
  • 创建com.dao.UserDao接口

    package com.dao;
    
    /**
     * @author 一宿君(CSDN : qq_52596258)
     * @date 2021-07-19 10:04:50
     */
    public interface UserDao {
    
        int saveUser();
    }
    
  • 创建com.dao.impl.UserDaoOracleImpl和UserDaomysqlImpl实现类

    package com.dao.impl;
    import com.dao.UserDao;
    /**
     * @author 一宿君(CSDN : qq_52596258)
     * @date 2021-07-19 10:05:25
     */
    public class UserDaoOracleImpl implements UserDao {
    
        @Override
        public int saveUser() {
            System.out.println("正在通过Oracle保存用户");
            return 0;
        }
    }
    
    package com.dao.impl;
    import com.dao.UserDao;
    /**
     * @author 一宿君(CSDN : qq_52596258)
     * @date 2021-07-19 10:06:12
     */
    public class UserDaoMySqlImpl implements UserDao {
        @Override
        public int saveUser() {
            System.out.println("正在通过MySql保存用户");
            return 0;
        }
    }
    
  • 创建com.service.UserService用户业务逻辑层接口

    package com.service;
    
    /**
     * @author 一宿君(CSDN : qq_52596258)
     * @date 2021-07-19 10:06:34
     */
    public interface UserService {
    
        int saveUser();
    
    }
    
  • 创建com.service.impl.UserServiceImpl业务逻辑层实现类

    package com.service.impl;
    import com.dao.UserDao;
    import com.service.UserService;
    
    /**
     * @author 一宿君(CSDN : qq_52596258)
     * @date 2021-07-19 10:07:24
     */
    @Service
    public class UserServiceImpl implements UserService {
    
        UserDao userDao;
    
        /**
         * 用于setter方法注入
         * @param userDao
         */
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    
        @Override
        public int saveUser() {
            return userDao.saveUser();
        }
    }
    
  • Spring核心配置文件applicationContext.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"
           xmlns:bean="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
           http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    
        <!--创建UserDaoOracleImpl的Bean实例-->
        <bean id="userDaoOracle" class="com.dao.impl.UserDaoOracleImpl"/>
        <!--创建UserDaoMySqlImpl的Bean实例-->
        <bean id="userDaoMySql" class="com.dao.impl.UserDaoMySqlImpl"/>
    
        <!--创建UserServiceImpl的Bean的实例-->
        <bean id="userService" class="com.service.impl.UserServiceImpl">
            <!--装配userDaoMySql的Bean实例-->
            <property name="userDao" ref="userDaoMySql"/>
        </bean>
        
    </beans>
    
  • 在没有使用基于Annotation注解之前,我们通过Spring的Bean工场创建Bean实例:

    在这里插入图片描述
    在这里插入图片描述

  • TestSpring测试类:

    public class TestSpring {
        public static void main(String[] args) {
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
            UserService userService = (UserService)applicationContext.getBean("userServiceImpl");
            userService.saveUser();
        }
    }
    
  • 运行结果:
    在这里插入图片描述

通过上述配置文件我们可以看出我们在使用类对象时,不再需要通过new来创建,二十通过Spring的Bean工厂为我们实现创建好,放入Ioc容器中,随时用随时取即可,方便了我们的操作,但是也有一个弊端,就是如果需要有很多实例的时候,我们就需要在配置文件中配置很多个Bean实例,这样会造成配置文件的臃肿,不利于后续的维护和扩展,所以就有了基于Annotation注解的方式,在每个实例类上使用@Component注解,即标注该类为Spring中的一个实例,如下:
在这里插入图片描述

  • applicationContext.xml配置文件中:
    在这里插入图片描述
  • 执行测试类TestSpring和上述配置文件中结果一样:
    在这里插入图片描述
  • 还要一点,我们可以看到上述注解类我们使用的都是@Component注解,当然这样可以实现,但是我们在开发过程中会做分层开发处理,当业务逐渐增多时,我们需要进行的事务处理,也自然就会累加,仅仅使用@Component注解是满足不了的,而且架构不够清晰明了,所以我们就引入了@Repository、@Service、@Controller等注解,但从名字上我们就可以看出分别作用于何层:
    在这里插入图片描述
    运行结果与上述一致,妥了!!!

以上是关于Spring系列基于Annotation(注解)的装配应用的主要内容,如果未能解决你的问题,请参考以下文章

Bean 注解(Annotation)配置- 通过注解加载Bean

annotation

注解(Annotation)

基于Annotation的IOC 初始化

Annotation

什么是Annotation