Java Spring框架的注解式开发你了解吗
时间:2022-11-12 10:11:53|栏目:JAVA代码|点击: 次
1. Spring框架的注解式开发
# Spring框架的注解式(Annotation)开发 1. 注解式开发 定义:通过Spring框架提供的一系列注解来完成项目中快速开发 注解:Annotation是java中一种特殊的类 类似于interface 使用时:@注解类名(属性=参数) @Param(Mybatis中做参数绑定的注解) 注意:Spring框架提供的这些注解日后仅仅能在和Spring去做一系列项目的时候去用,这是Spring框架为我们提供的。 为什么Spring框架要提供这么一套注解去帮助我们呢,原因是现有的开发方式中开发效率很低下,随着组件的增多, 比如UserService、UserAction...大家会发现在做现有的配置文件进行开发时,每写一个业务层,就需要在spring.xml 文件中通过bean标签去注册,有的时候忘了在工厂中注册的时候,用的时候还会产生空指针异常问题。所以Spring框架为了让大家 专注于业务逻辑处理,不想每次开发一个组件时还要去写一个配置,每次开发一个组件时还需要写一个配置这样是不是影响了开发 效率啊。所以Spring框架就想了,能不能为程序员提供一种便利呢,这种便利就是日后不需要它再做配置就完成工厂创建、注入 相关的一些操作,怎么去做呢。所以在Spring中它给我们提供了一系列的相关注解帮助我们去做快速开发。 2. spring中的注解 前置条件:必须在工厂配置文件中完成注解的扫描 <!--下面这个标签就是用来做注解扫描的 base-package:指定扫描哪些包的注解--> <context:component-scan base-package="com.baizhi"> 在用注解的时候能让spring框架去看到这些注解或者说去扫描到这些注解, 那spring框架怎么去读呢,spring有一个spring.xml这样的一个配置文 件,是不是得让加载这个配置时要通过这个配置文件扫描到注解啊。 1). 创建对象相关注解 @Component注解 通用组件创建注解 父类注解 作用:用来负责对象的创建 ==========> 简化<bean class="" id=""> 修饰范围:只能用在类上 注意:默认使用这个注解在工厂中创建的对象的唯一标识为 类名首字母小写 UserDAOImpl ===> userDAOImpl value属性的作用:用来指定创建的对象在工厂中的唯一标识 推荐:存在接口则名字设置为接口首字母小写 不存在使用默认 @Component("userDAO") 等价于 @Component(value = "userDAO") 子类注解:沿用了父类注解的一切特性,也就是说下面三个注解也能用来创建对象 @Repository 作用:一般用来创建DAO中组件的注解 @Service 作用:一般用来创建Service中组件的注解 @Controller 作用:一般用来创建Action中组件的注解 2). 控制对象在工厂中创建次数 默认工厂单例创建 a. 配置文件修改 <bean class="" id="" scope="singleton|prototype"> b. 注解如何控制 @Scope 作用: 用来指定对象的创建次数默认单例 修饰范围:只能加在类上 value属性:singleton 单例 默认|prototype 多例 @Scope("prototype") =====> 等价于 @Scope(value = "prototype") @Scope("singleton") =====> 等价于 @Scope(value = "singleton")默认是单例,如果想设置为单例,可以不写 注意:在管理structs的action时必须加入@Scope注解值必须为prototype 3). 属性注入的相关注解 下面两个都能用 a. spring框架提供的 @Autowired :注意 默认根据类型进行注入 推荐 b. javaEE本身就有的 @Resource :注意 默认根据名字注入,名称找不到时自动根据类型进行注入 修饰范围:用在类中的成员变量或者是用在类中成员变量的SET方法上 作用 :用来完成成员变量的赋值|注入操作 注意:使用注解进行注入时,日后注入的成员变量可以不再提供SET方法 4). 控制事务的注解 @Transactional 作用:用来给类种方法加入事务控制 简化配置文件中 两段配置 1. 事务通知及事务细粒度配置 2. 简化事务切面配置 修饰范围:类 | 方法上 局部优先原则 1. 加载类上 代表类中所有方法加入事务控制 2. 加在方法上 代表当前方法加入事务控制 3. 类和方法同时存在 方法优先 使用要求:如果想要让@Transactional这个注解生效必须在配置文件中加入如下注解: <!--开启注解式事务生效--> <!--必须是tx结尾的包下的--> <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven> 注解属性: @Transactional(propagation = Propagation.SUPPORTS, isolation = Isolation.READ_COMMITTED, rollbackFor = {java.lang.RuntimeException.class}, noRollbackFor = {}, readOnly = false, timeout = -1) // 当然这些都推荐大家使用默认,唯独有一个方法有点特殊,就是查询方法,不需要去明确 // 的把它加入事务,所以建议在查询方法上@Transactional(propagation = //Propagation.SUPPORTS)让它去支持事务 注意:使用了@Transactional注解代理原有配置文件中的创建事务环绕通知细粒度控制和配置事务切面这两段配置 <!--创建事务环绕通知并进行事务细粒度控制--> <!--transaction-manager找ref --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*"/> <tx:method name="update*"/> <tx:method name="delete*"/> <tx:method name="find*" propagation="SUPPORTS"/> </tx:attributes> </tx:advice> <!--配置事务切面--> <aop:config> <aop:pointcut id="pc" expression="execution(* com.baizhi.service.*ServiceImpl.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/> </aop:config> 但是下面的这些配置该写还得写 <!--创建数据源--> <bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/lb?characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <!--创建sqlSessionFactoy--> <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory"> <!--注入datasource mapperLocations typeAliasesPackage--> <property name="dataSource" ref="dataSource"/> <property name="mapperLocations" value="classpath:com/baizhi/mapper/*.xml"/> <property name="typeAliasesPackage" value="com.baizhi.eneity"/> </bean> <!--创建DAO--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!--注入sqlSessionFactory dao接口所在包--> <!--value要的是sqlSessionFactory在工厂中的名字--> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> <property name="basePackage" value="com.baizhi.dao"/> </bean> <!--创建事务管理器--> <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
1.1 开启注解扫描配置
<!--开启注解扫描--> <context:component-scan base-package="com.baizhi"/>
1.2 实例化相关注解
# 1. @Component(value="userService") 修饰范围: 用在类上 注解作用: 通用的创建实例的注解,用来创建当前这个类的实例 value属性: 用来指定创建的对象在工厂中的唯一标识 如果不指定默认创建对象在工厂中的标识为类名首字母小写 # 2. @Repository 修饰范围: 用在类上 注解作用: @component的子类注解专用于DAO组件的创建,通常加在DAO组件上 value属性: 用来指定创建的对象在工厂中的唯一标识 如果不指定默认创建对象在工厂中的标识为类名首字母小写 # 3. @Service 修饰范围: 用在类上 注解作用: @component的子类注解专用于Service组件的创建,通常加在Service组件上 value属性: 用来指定创建的对象在工厂中的唯一标识 如果不指定默认创建对象在工厂中的标识为类名首字母小写 # 4. @Controller 修饰范围: 用在类上 注解作用: @component的子类注解专用于Action组件的创建,通常加在Action组件上 value属性: 用来指定创建的对象在工厂中的唯一标识 如果不指定默认创建对象在工厂中的标识为类名首字母小写 注:除了以上三种DAO、Service、Action三种组件分别创建时使用三种子类注解,其余的组件创建时使用 @Component注解
@Repository("userDAO") public class UserDAOImpl implements UserDAO{
@Service("userService")public class UserServiceImpl implements UserService{
1.3 控制对象的创建次数的注解
# 1. @Scope(value="singleton|prototype") 修饰范围: 用在类上 注解作用: 用来控制这个实例在工厂中的创建次数 value属性: singleton为单例,prototype为多例 默认单例
@Service("userService") @Scope("prototype") public class UserServiceImpl implements UserService{
1.4 注入相关的注解
# 1. @Autowired(Spring提供) 修饰范围: 用在成员变量或成员变量的GET/SET方法上 注解作用: 用来给类中成员变量赋值 注入原则: 默认根据类型自动注入 # 2. @Resource(JAVAEE提供) 修饰范围: 用在成员变量或成员变量的GET/SET方法上 注解作用: 用来给类中成员变量赋值 注入原则: 默认根据名称自动注入名称找不到根据类型自动注入 注意:使用注解进行注入时,日后注入的成员变量可以不再提供SET方法
@Service("userService") @Scope("prototype") public class UserServiceImpl implements UserService{ @Autowired private UserDAO userDAO;
1.5 控制事务的相关注解
# 1. @Transactional 修饰范围: 用在类上主要用在业务层组件类上或者是方法上 注解作用: 用来给类中方法加入事务,当类上和方法上同时存在该注解时局部优先 注解属性: propagation 用来控制传播属性 赋值时使用枚举类 Isolation 用来控制隔离级别 赋值时使用枚举类 一般使用默认 timeout 用来设置超时性 赋值代表超时时间 一般使用默认 rollback-for 用来设置什么异常回滚 赋值时给class 一般使用默认 norollback-for 用来设置什么异常不会滚 赋值时给class 一般使用默认 readonly 用来设置事务读写性 true/false 一般使用默认 注意:如果要使用事务注解在配置文件中必须开启事务注解生效加入如下配置: <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven> 使用事务相关注解只可以简化配置文件中 两段配置 1. 事务通知及事务细粒度配置 2. 简化事务切面配置 但是其他的比如创建数据源、创建sqlSessionFactoy、创建DAO、创建事务管理器还是要写的 因为对于增、删、改的事务属性我们一般都使用默认,在进行事务控制时只需要在类上加一个@Transactional即可,属性不写即 代表使用默认,但是对于查询方法我们要加入局部注解@Transactional(propagation = Propagation.SUPPORTS)使查询 方法支持事务
// 事务的使用 一般在给类加控制事务的注解时,不修改属性,使用默认,下面只是为了演示注解的使用 @Service("userService") @Scope("prototype") @Transactional(propagation = Propagation.SUPPORTS, isolation = Isolation.READ_COMMITTED, rollbackFor = {java.lang.RuntimeException.class}, noRollbackFor = {}, readOnly = false, timeout = -1) // 当然这些都推荐大家使用默认,唯独有一个方法有点特殊,就是查询方法,不需要去明确的 // 把它加入事务,所以建议在查询方法上@Transactional(propagation = Propagation.SUPPORTS) // 让它去支持事务 public class UserServiceImpl implements UserService{
// 平常使用 @Service("userService") @Scope("prototype") public class UserServiceImpl implements UserService{ @Autowired private UserDAO userDAO; public void save(String name) { userDAO.save(name); System.out.println("Service:" + name); } @Transactional(propagation = Propagation.SUPPORTS) public void find() { } }
注意:在使用控制事务的注解时,需要给类加上不修改任何属性的注解@Transactional,另外还需要给find查询方法加上局部注解@Transactional(propagation = Propagation.SUPPORTS)