赞
踩
他们的作用和在xml中编写一个bean标签实现的功能是一样的
@Component作用:用于把当前类对象存入spring容器中(beans.xml配置约束context)
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 告知spring在创建容器的时候要扫描的包,配置conext名称空间和约束,在croe中搜索xmlns:context-->
<context:component-scan base-package="com.ming"></context:component-scan>
</beans>
value属性:用于指定bean的id,不写时默认是当前类名首字母小写
@Component衍生的注解:
@controller:一般用在表现层
@service:一般用在业务层
@Repository:一般用在持久层
这三个注解作用和属性与component一样,spring框架提供的明确的三层使用注解,使我们的三层对象更加清晰
他们的作用和在xml中的bean标签内写一个property标签作用是一样的
@Autowired作用:自动按照类型注入。先按类型找,然后按名称找。只要容器中有唯一的一个bean对象类型和注入的变量类型匹配,就可以注入成功
出现位置:变量和方法上
@Qualifier作用:按照类型注入的基础之上再按照名称注入。它在给类成员注入的时候不能单独使用必须和Autowired组合一起使用,在给方法参数注入的时候可以单独使用。
@Resource作用:按照名称注入,可以单独使用。先按名称找,然后按类型找
属性name:用于指定bean的id
总结:以上三个注解注入数据的时候只能注入bean类型的数据,而基本类型和String类型无法使用上述注解实现,另外集合类型的注入只能通过xml来实现
@value:注入基本数据类型和String类型的数据
属性:value用于指定数据的值,可以使用SpEL(EL表达式),spel写法:${}
他们的作用和在bean标签上使用scpoe属性是一样的
@scope作用:用于指定bean的作用范围
value:指定范围的取值 singleton prototype
他们的作用就和在bean标签中使用init-method和destroy-method是一样的
@PreDestroy作用用于销毁方法 @PostConstruct用于初始化方法
持久层用的是dbutils
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.3.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.11</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.2.3.RELEASE</version> </dependency> <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> </dependencies>
mysql:创建表
CREATE TABLE account (
id int PRIMARY KEY AUTO_INCREMENT,
name varchar(40),
money float
)CHARACTER SET utf8 COLLATE utf8_general_ci;
创建业务层接口:
package com.ming.service; import com.ming.model.Account; import java.util.List; /** * 账户业务层接口 */ public interface IAccountService { /** * 查找所有的账户 * * @return */ List<Account> findAll(); /** * 按照id查找账户 * * @param id * @return */ Account findById(Integer id); /** * 保存 * * @param account */ void saveAccount(Account account); /** * 更新 * * @param account */ void updateAccount(Account account); /** * 删除 * * @param id */ void deleteAccount(Integer id); /** * @param sourceName 转出账户 * @param targetName 转入账户 * @param money 金额 */ public void transfer(String sourceName, String targetName, Float money); }
业务层实现类:
package com.ming.service.impl; import com.ming.dao.IAccountDao; import com.ming.model.Account; import com.ming.service.IAccountService; import com.ming.util.TransacationManger; import java.util.List; /** * 账户的业务层实现类 */ public class AccountServiceImpl implements IAccountService { //最早的写法 //private IAccountDao accountDao = new AccountDaoImpl(); //BeanFactory读取配置的bean.properties的dao //private IAccountDao accountDao= (IAccountDao) BeanFactory.getBean("accountDao"); private IAccountDao accountDao; private TransacationManger tx; public void setAccountDao(IAccountDao accountDao) { this.accountDao = accountDao; } public void setTx(TransacationManger tx) { this.tx = tx; } @Override public List<Account> findAll() { return accountDao.findAll(); } @Override public Account findById(Integer id) { return accountDao.findById(id); } @Override public void saveAccount(Account account) { accountDao.saveAccount(account); } @Override public void updateAccount(Account account) { accountDao.updateAccount(account); } @Override public void deleteAccount(Integer id) { accountDao.deleteAccount(id); } @Override public void transfer(String sourceName, String targetName, Float money) { Account sourceAccount = accountDao.findAccountByName(sourceName); sourceAccount.setMoney(sourceAccount.getMoney() - money); accountDao.updateAccount(sourceAccount); Account targetAccount = accountDao.findAccountByName(targetName); int a = 4 / 0; targetAccount.setMoney(targetAccount.getMoney() + money); accountDao.updateAccount(targetAccount); } }
账户持久层接口:
package com.ming.dao; import com.ming.model.Account; import java.util.List; /** * 账户的持久层接口 */ public interface IAccountDao { List<Account> findAll(); Account findById(Integer id); void saveAccount(Account account); void updateAccount(Account account); void deleteAccount(Integer id); //根据账户名称查询账户,为了演示事物准备 Account findAccountByName(String accountName); }
账户持久层实现类:
package com.ming.dao.impl; import com.ming.dao.IAccountDao; import com.ming.model.Account; import com.ming.util.ConnectionThredUtil; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import java.util.List; public class AccountDaoImpl implements IAccountDao { private QueryRunner queryRunner; private ConnectionThredUtil conn; public void setQueryRunner(QueryRunner queryRunner) { this.queryRunner = queryRunner; } public void setConn(ConnectionThredUtil conn) { this.conn = conn; } public List<Account> findAll() { try { return queryRunner.query(conn.getThredConnection(), "select * from account ", new BeanListHandler<Account>(Account.class)); } catch (Exception e) { throw new RuntimeException(e); } } public Account findById(Integer id) { try { return queryRunner.query(conn.getThredConnection(), "select * from account where id = ? ", new BeanHandler<Account>(Account.class), id); } catch (Exception e) { throw new RuntimeException(e); } } public void saveAccount(Account account) { try { queryRunner.update(conn.getThredConnection(), "insert into account(name,money) values(?,?)", account.getName(), account.getMoney()); } catch (Exception e) { throw new RuntimeException(e); } } public void updateAccount(Account account) { try { queryRunner.update(conn.getThredConnection(), "update account set name=? ,money=? where id=? ", account.getName(), account.getMoney(), account.getId()); } catch (Exception e) { throw new RuntimeException(e); } } public void deleteAccount(Integer id) { try { queryRunner.update(conn.getThredConnection(), "delete account where id=?", id); } catch (Exception e) { throw new RuntimeException(e); } } @Override public Account findAccountByName(String accountName) { try { return queryRunner.query(conn.getThredConnection(), "select * from account where name = ? ", new BeanHandler<Account>(Account.class), accountName); } catch (Exception e) { throw new RuntimeException(e); } } }
bean.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" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- =============基于xml的IOC配置===============--> <!-- 配置service对象--> <bean id="accountService" class="com.ming.service.impl.AccountServiceImpl"> <!-- 注入dao对象--> <property name="accountDao" ref="accountDao"></property> </bean> <!-- 配置dao对象--> <bean id="accountDao" class="com.ming.dao.impl.AccountDaoImpl"> <!-- 注入queryRunner对象--> <property name="queryRunner" ref="runner"></property> </bean> <!-- 配置QueryRunner,它是单例对象所以配置作用域scope--> <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"> <!--注入数据源没有提供set方法,只能用构造函数注入--> <constructor-arg name="ds" ref="dataSource"></constructor-arg> </bean> <!--注入数据源--> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!--注入连接数据库的必备信息--> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property> <property name="user" value="root"></property> <property name="password" value="root"></property> </bean> </beans>
基于XML的IOC配置用Junit测试
package com.ming.test; import com.ming.model.Account; import com.ming.service.IAccountService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.List; /** * 基于xml的IOC配置使用Junit单元测试 */ public class AccountServiceTest { @Test public void testFindAll() { //1.获取容器 ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); //2.得到业务层对象 IAccountService accountService = (IAccountService) context.getBean("accountService"); List<Account> accountList = accountService.findAll(); System.out.println(accountList); } @Test public void testFindById() { ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); IAccountService accountService = (IAccountService) context.getBean("accountService"); Account account = accountService.findById(1); System.out.println(account); } @Test public void testSaveAccount() { ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); IAccountService accountService = (IAccountService) context.getBean("accountService"); Account account = new Account(); account.setName("aaa"); account.setMoney(1000f); accountService.saveAccount(account); } @Test public void testUpdateAccount() { ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); IAccountService accountService = (IAccountService) context.getBean("accountService"); Account account = new Account(); account.setName("aaa"); account.setMoney(1000f); accountService.updateAccount(account); } @Test public void testDeleteAccount() { ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); IAccountService accountService = (IAccountService) context.getBean("accountService"); accountService.deleteAccount(1); } }
@configuration
作用:指定当前类是一个配置类 等同于bean.xml
细节:当配置作为AnnotationConfigApplictionContext创建对象的参数时,可以不写。
扫描包的时候首先会扫描这个包下的类,首先这个类要是一个配置类,才会去扫描这个类中的注解
@ComponentScan
作用:用于通过注解告知spring在创建容器时要扫描的包
属性value和basePackages可以互换:它和beans.xml中base-package的作用是一样的,都是用于指定创建容器时要扫描的包。
等同于: <context:component-scan base-package=“com.ming”></context:component-scan>
@Bean
作用在方法上,表示通过方法来定义一个bean,默认方法的名称作为bean的名称,将方法的返回值作为bean对象,注册到spring容器中
@import
用于导入其他配置类
@PropertySource
用于指定properties文件的位置
纯注解的方式和xml的方式比起来更费劲,尽量选择xml和注解结合使用。
属性value:用于指定文件名称和路径 关键字classpath:类路径下的文件
总结:如果是第三方jar用xml,本地代码用注解方便
1.bean.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" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!-- =============基于注解的IOC配置===============--> <!--告知spring创建容器时要扫描的包--> <context:component-scan base-package="com.ming"></context:component-scan> <!-- 配置QueryRunner,它是单例对象所以配置作用域scope--> <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"> <!--注入数据源没有提供set方法,只能用构造函数注入--> <constructor-arg name="ds" ref="dataSource"></constructor-arg> </bean> <!--注入数据源--> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!--注入连接数据库的必备信息--> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3307/test"></property> <property name="user" value="liming"></property> <property name="password" value="liming"></property> </bean> </beans>
总结:bean.xml中有两个配置没有用注解(第三方jar和component-scan),用@Bean注解解决。
Spring配置类:
package com.ming.config; import com.ming.util.JdbcProConfig; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.PropertySource; /** * 该类是一个配置类,它的作用和bean.xml是一样的 */ @Configuration @ComponentScan(basePackages = {"com.ming"}) @PropertySource("classpath:jdbc.properties") @Import(value = JdbcProConfig.class) public class SpringConfiguration { }
当 @ComponentScan(basePackages = {"com.ming"})注解出现时,bean.xml中的 <context:component-scan base-package="com.ming"></context:component-scan>配置可以注释掉,因为作用是相同的。
jdbc.properties文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3307/test
user=liming
pwd=liming
@Import导入类:
package com.ming.util; import com.mchange.v2.c3p0.ComboPooledDataSource; import org.apache.commons.dbutils.QueryRunner; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Scope; import javax.sql.DataSource; /** * jdbc配置类,用于@import注解导入 */ public class JdbcProConfig { @Value("${driver}") private String driver; @Value("${url}") private String url; @Value("${user}") private String user; @Value("${pwd}") private String pwd; /** * 该注解可以将一个方法的返回值注册到spring容器中 * @param dataSource * @return */ @Bean(name="queryRunner") @Scope("prototype") public QueryRunner getQueryRunner(DataSource dataSource){ return new QueryRunner(dataSource); } @Bean(name="dataSource") public DataSource getDataSource() { try { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(driver); dataSource.setJdbcUrl(url); dataSource.setUser(user); dataSource.setPassword(pwd); return dataSource; } catch (Exception e) { throw new RuntimeException(e); } } }
分析:
1.应用程序的入口 main方法
2.junit单元测试中,没有main方法也能执行,junit集成了main方法,该方法会判断当前类中哪些方法有@test注解,Junit就会让@test注解的方法执行
3.junit不会管我们是否采用spring框架,在执行测试方法的时候Junit根本不会知道我们使用了spring框架,所以也就不会为我们读取配置文件/配置类,也就不会为我们创建spring核心容器。
4。总结以上三点可知,当我们执行测试方法时,没有IOC容器,就算写了@AutoWired注解,也无法实现注入。
所以在执行test方法时,要创建spring核心容器。
spring整合Junit的配置:
1.导入spring整合Junit的jar(spring-test)
2.使用spring提供的一个注解把原有的main方法替换了,替换成spring提供的@RunWith(SpringJUnit4ClassRunner.class)
3.告知spring的运行器,spring的IOC创建时基于xml还是注解的,并说明位置 locations指定xml的文件位置 classes指定注解类所在的位置@ContextConfiguration(classes = SpringConfiguration.class)
package com.ming.test; import com.ming.config.SpringConfiguration; import com.ming.model.Account; import com.ming.service.IAccountService; import com.ming.util.AccountProxy; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.List; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SpringConfiguration.class) public class AccountTest { @Autowired private IAccountService accountService; @Test public void addTest() { Account account = new Account(); account.setName("ddd"); account.setMoney(1000f); accountService.saveAccount(account); } @Test public void findAllTest() { List<Account> li = accountService.findAll(); System.out.println(li); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。