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 | 一般作用在一个共用模块类上,该模块中有多个影响类的公共行为,我们称之为切面,该注解的作用就是把当前的切面类标识为一个切面共容易读取 |
@Pointcut | Pointcut是织入Advice的触发条件,每个Pointcut的定义包括2两部分,一是:表达式;二是:方法签名。方法签名必须是public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码 |
@Around | 环绕增强,相当于MethodInterceptor |
@Before | 前置增强,相当于BeforeAdvice的功能 |
@AfterReturning | 后置增强,想当于AfterReturningAdvice,方法正常退出时执行 |
@AfterThrowing | 异常抛出增强,相当于ThrowsAdvice |
@After | final最终增强,不管是抛出异常还是正常退出都会执行 |
@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(注解)的装配应用的主要内容,如果未能解决你的问题,请参考以下文章