一、Spring 基于 Annotation 装配 Bean 对象
Spring 基于 Annotation 装配 Bean 对象
在 Spring 中,尽管使用 XML 配置文件可以实现 Bean 的装配工作,但如果应用中Bean 的数量较多,会导致 XML 配置文件过于臃肿,从而给维护和升级带来一定的困难。
在 Spring 框架中提供了一些用于装配 Bean 对象的注解用于替换 xml 文件的中配置。
1 jar 包依赖
Spring 核心容器模块
spring-beans-5.2.7.RELEASE.jar
spring-context-5.2.7.RELEASE.jar
spring-core-5.2.7.RELEASE.jar
spring-expression-5.2.7.RELEASE.jar
Spring AOP 模块
spring-aop-5.2.7.RELEASE.jar
Commons-Loggin 日志
commons-logging-1.2.jar
2 在 Spring 的配置文件中开启注解扫描
<context:component-scan base-package="扫描注解的包名"/>
3 注册 Bean 对象
3.1@Component
可以使用此注解描述 Spring 中的 Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需将该注解标注在相应类上即可。
3.2@Service
通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
3.3@Repository
于将数据访问层(DAO 层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
3.4@Controller
通常作用在控制层(如 Spring MVC 的 Controller),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
4 Bean 对象依赖注入注解
4.1@Autowired
用于对 Bean 的属性变量、方法及构造方法进行标注,完成 Bean 的自动注入处理。
@Autowired 按照 Bean 的类型进行装配。
4.2 @Resource
其作用与 Autowired 一样。其区别在于 @Autowired 按照 Bean 类型装配,而@Resource 是可以按照 Bean ID 或者类型进行装配。
4.3 @Qualifier
与 @Autowired 注解配合使用,会将默认的按 Bean 类型装配修改为按 Bean 的实例名称装配,Bean 的实例名称由 @Qualifier 注解的参数指定。
4.4 @Value
可获取 Properties 文件中的值。
5 Spring 配置相关注解
5.1 @Configuration
声明当前类为配置类,相当于 xml 形式的 Spring 配置。该注解需要添加到类上。
5.2 @Bean
注解在方法上,声明当前方法的返回值为一个 Bean 对象,该对象会被添加 SpringIOC容器中。和<bean>标签作用的相同。Bean 的实例名称由@Qualifier 注解的参数指定。
二、Spring注解案例
1.1 给POJO类添加注解
Users.java:
package com.dyh.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
// <bean id="users" class="com.dyh.pojo.Users" /> 组件
@Component
public class Users {
@Value("1")
private Integer userId;
@Value("admin")
private String userName;
private String userSex;
@Value("M")
public void setUserSex(String userSex) {
this.userSex = userSex;
}
// 其余方法略
}
Orders.java:
@Component(value = "orders")
public class Orders {
@Value("1")
private Integer orderId;
@Value("999")
private Double orderPrice;
// 其余方法略
}
1.2 PojoConfig.java
package com.dyh.pojo;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan
public class PojoConfig {
}
1. 测试类
public class TestAnBean {
public static void main(String[] args) {
ApplicationContext ac
= new AnnotationConfigApplicationContext(PojoConfig.class);
Users users = ac.getBean("users", Users.class);
System.out.println(users);
Orders orders = ac.getBean("orders", Orders.class);
System.out.println(orders);
/*UsersDAO usersDAO = ac.getBean("usersDAO",UsersDAO.class);
System.out.println(usersDAO);*/
OrdersDAO ordersDAO = ac.getBean("ordersDAO",OrdersDAO.class);
System.out.println(ordersDAO);
}
}
运行结果:
2、注解实现事务控制
2.1 DAO实现类添加注解
UsersDAOImpl.java:注意组件名为UsersDAOImpl。
@Repository("UsersDAOImpl")
public class UsersDAOImpl implements UsersDAO {
@Autowired
private JdbcTemplate jdbcTemplate;
OrdersDAOImpl.java:注意组件名为ordersDAO。
@Repository("ordersDAO")
public class OrdersDAOImpl implements OrdersDAO {
@Autowired
private JdbcTemplate jdbcTemplate;
2.2 Service层实现类添加注解
UsersServiceImplAn.java:
@Service("usersService")
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public class UsersServiceImplAn implements UsersService {
@Autowired
@Qualifier("UsersDAOImpl") // 注意名称跟DAO层的组件名一致
private UsersDAO usersDAO;
/*@Autowired
@Qualifier("ordersDAO")*/
@Resource(name="ordersDAO") // 等价与上面两个注解的组合
private OrdersDAO ordersDAO;
2.3 JDBC配置
2.3.1 db.properties文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456
2.3.2 JdbcConfig.java
配置数据源dataSource和JDBCTemplate的Bean。
@PropertySource(value = "classpath:com/dyh/config/db.properties",encoding ="utf-8")
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean(name = "dataSource")
public DataSource getDataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(this.driverClassName);
dataSource.setUrl(this.url);
dataSource.setUsername(this.username);
dataSource.setPassword(this.password);
/*
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/spring");
dataSource.setUsername("root");
dataSource.setPassword("123456");
*/
return dataSource;
}
@Bean(name="jdbcTemplate")
public JdbcTemplate getJdbcTemplate(DataSource dataSource){
return new JdbcTemplate(dataSource);
}
}
配置完成后是为了自动注入到DAO层实现类的依赖jdbcTemplate。
2.4 TransactionConfig.java
事务控制组件:
public class TransactionConfig {
@Bean(name="transactionManager")
public DataSourceTransactionManager createTransactionManager(DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
}
2.5 SpringConfiguration.java
Spring的主配置文件:
@Configuration
@ComponentScan("com.dyh")
@Import({JdbcConfig.class, TransactionConfig.class})
@EnableTransactionManagement
public class SpringConfiguration {
}
2.6 TestAnTx测试
public class TestAnTx {
public static void main(String[] args) {
ApplicationContext ac
= new AnnotationConfigApplicationContext(SpringConfiguration.class);
UsersService usersService = ac.getBean("usersService", UsersService.class);
Users user = ac.getBean("users", Users.class);
Orders order = ac.getBean("orders", Orders.class);
usersService.addUserAndOrder(user, order);
}
}
运行结果:
人为模拟异常后的运行结果:
三、整合Spring的Junit测试
package com.dyh.test;
import com.dyh.config.SpringConfiguration;
import com.dyh.pojo.Orders;
import com.dyh.pojo.Users;
import com.dyh.service.UsersService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class AnTxSpringJUnit4Test {
@Resource(name="usersService")
private UsersService usersService;
public void setUsersService(UsersService usersService) {
this.usersService = usersService;
}
@Test
public void testAddUsersAndOrders(){
System.out.println(usersService);
Users user = new Users(null, "admin", "M");
Orders order = new Orders(null, 999.0);
usersService.addUserAndOrder( user, order);
}
}
不发生异常的情况下,测试通过,两张表中各成功插入一条数据,发生异常的情况下,测试未通过,数据库数据回滚,users表和orders表都没有数据。