applicationContext的三个实现类
ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、AnnotationConfigApplicationContext
前两者的区别是:一个从classpath路径下读取资源文件,而另一个则可以从系统的任意位置读取,从名字即可get。
beanFactory和applicationContext区别
beanFactory适合于什么时候用什么时候创建,即适合多例对象模式,applicationContext适合单例对象模式,因为只需要创建一次,早创建早完事。
spring对bean的管理细节
-
1.创建bean的三种方式
-
2.bean对象的作用范围
-
3.bean对象的生命周期
依赖注入
依赖注入介绍:
- 构造函数注入
优点:可以满足必须初始化的需求
缺点:改变了bean对象实例化的方式
set方法注入
bean中的name是根据setXxx方法中的Xxxx变为小写 xxx的名称,而不是定义的属性变量。
特别的,复杂类型的注入,主要分为集合和map类型,集合类型在property标签内嵌 等即可。map类型在property标签嵌入
注解注入
用于创建对象:@Component,
作用:把当前类对象(键[bean id]->值[值是创建的类实例])存入spring容器中.
属性:value,用于指定bean的id,如果不写,默认将类名的首字母改为小写,对应。
@Component(value="userServiceImpl")
//只有一个参数时,value可以省略,value作用就是指定bean id
public class UserServiceImpl implements UserService {
public void destory()
{
System.out.println("destory 方法执行");
}
public void init()
{
System.out.println("init 方法执行");
}
public void userinfosave()
{
System.out.println("usrinfo save 方法执行");
}
}
// 配置文件:
<?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">
<context:component-scan base-package="com"></context:component-scan>
</beans>
注解:@Controller:一般用于表现层
注解:@Service:用于业务层
注解:@Repository:用于持久层
以上三个注解的作用与@Component作用一摸一样,它们三个是spring框架提供的明确的三层注解,
@autowired 自动按照类型注入,直接在容器中,找map对应的 value,xxx
@Scope,设置bean的作用范围。
@Qulifier 指定bean 的id进行装配
@Scope+@Qulifier==@Resource(根据bean id装配),@Resource(name=“xxx”)
附带一个简单的数据库CURD操作的小demo.
User.java
package com.domain;
public class User {
private Integer uid;
private String username;
private String password;
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"uid=" + uid +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
UserServiceImpl.java
package com.service.impl;
import com.dao.UserDao;
import com.domain.User;
import com.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDaoimpl=null;
public void userinfosave()
{
System.out.println("userinfow shwo tets");
}
public List<User> findAllUsers() {
return userDaoimpl.findAllUsers();
}
public User findOneUserById(Integer uid) {
return userDaoimpl.findOneUserById(uid);
}
public void saveUser(User user) {
userDaoimpl.saveUser(user);
}
public void updateUserById(User user) {
userDaoimpl.updateUserById(user);
}
public void deleteUserById(Integer uid) {
userDaoimpl.deleteUserById(uid);
}
}
UserDaoImpl.java
package com.dao.impl;
import com.dao.UserDao;
import com.domain.User;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* 账户的持久层实现类
*/
@Repository(value="userDaoImpl1")
public class UserDaoImpl implements UserDao
{
@Autowired
private QueryRunner runner;
public void setRunner(QueryRunner runner) {
this.runner = runner;
}
public void showUserDao()
{
System.out.println("userdao info pring 2222");
}
public List<User> findAllUsers() {
try
{
return runner.query("select * from users",new BeanListHandler<User>(User.class));
}catch(Exception e)
{
throw new RuntimeException(e);
}
}
public User findOneUserById(Integer uid) {
try
{
return runner.query("select * from users where uid=?",new BeanHandler<User>(User.class),uid);
}catch(Exception e)
{
throw new RuntimeException(e);
}
}
public void saveUser(User user) {
try
{
runner.update("insert into users(username,password) values(?,?)",user.getUsername(),user.getPassword());
}catch(Exception e)
{
throw new RuntimeException(e);
}
}
public void updateUserById(User user) {
try
{
runner.update("update users set username=?,password=? where uid = ?",user.getUsername(),user.getPassword(),user.getUid());
}catch(Exception e)
{
throw new RuntimeException(e);
}
}
public void deleteUserById(Integer uid) {
try
{
runner.update("delete from users where uid = ?",uid);
}catch(Exception e)
{
throw new RuntimeException(e);
}
}
}
UserService.java
package com.service;
import com.domain.User;
import java.util.List;
public interface UserService {
public void userinfosave();
/**
* 查询所有
* @return
*/
List<User> findAllUsers();
/**
* 根据id查询用户
* @return
*/
User findOneUserById(Integer uid);
/**
* 保存
* @return
*/
void saveUser(User user);
/**
* 更新
* @return
*/
void updateUserById(User user);
/**
* 删除
* @return
*/
void deleteUserById(Integer uid);
}
UserDao.java
package com.dao;
import com.domain.User;
import java.util.List;
public interface UserDao {
public void showUserDao();
/**
* 查询所有
* @return
*/
List<User> findAllUsers();
/**
* 根据id查询用户
* @return
*/
User findOneUserById(Integer uid);
/**
* 保存
* @return
*/
void saveUser(User user);
/**
* 更新
* @return
*/
void updateUserById(User user);
/**
* 删除
* @return
*/
void deleteUserById(Integer uid);
}
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"
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">
<context:component-scan base-package="com"></context:component-scan>
<!--配置QueryRunner -->
<bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
<!--注入数据源-->
<constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean>
<bean name="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="123456"></property>
</bean>
</beans>
测试:
package com.test;
import com.domain.User;
import com.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
/**
* 使用Junit测试我们的方法
*/
public class UserServiceTest {
@Test
public void testFindAll() {
//1.获取容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.得到业务对象
UserService usv= (UserService)ac.getBean("userServiceImpl");
List<User> ulist = usv.findAllUsers();
//3.执行方法
for(User us:ulist)
{
System.out.println(us);
}
}
@Test
public void testFindOne() {
//1.获取容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.得到业务对象
UserService usv= (UserService)ac.getBean("userServiceImpl");
Integer uid = 8;
User ures = usv.findOneUserById(uid);
System.out.println(ures);
}
@Test
public void testSave() {
User user = new User();
user.setUsername("orange");
user.setPassword("999");
//1.获取容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.得到业务对象
UserService usv= (UserService)ac.getBean("userServiceImpl");
usv.saveUser(user);
}
@Test
public void testUpdate() {
User u = new User();
u.setUid(10);
u.setPassword("123999");
u.setUsername("uuu hr");
//1.获取容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.得到业务对象
UserService usv= (UserService)ac.getBean("userServiceImpl");
usv.updateUserById(u);
}
@Test
public void testDel() {
//1.获取容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.得到业务对象
UserService usv= (UserService)ac.getBean("userServiceImpl");
usv.deleteUserById(12);
}
}
注解注入
上述使用的注解方式是由xml文件配置的方式转变而来,尽管在使用上,已经用了很多注解,但是xml文件仍然还在,接下来将使用@Configuration、@ComponentScan两个注解,实现将xml文件消除。
创建SpringConfiguratioin。
注意注释中对于Bean的介绍。
package config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import javax.sql.DataSource;
/**
* 该类是一个配置类,作用等同bean.xml
* Configuration
* 作用,表明当前类是一个配置类
* ConponentScan
* 作用:用于通过注解指定spring在创建容器时需要扫描的包
* 属性:basePackages 和values作用一样
* values:它和basePackages一样,都是用于指定创建容器时要扫描的包,我们使用此注解,就等同在xml配置文件中配置了
* <context:component-scan base-package="com"></context:component-scan>
* Bean
* 作用:用于把当前方法的返回值作为bean对象,存入spring的ioc容器中
* 属性:
* name:用于指定bean的id。默认值,当不写时,默认当前方法的名称
* 细节:当我们使用注解配置方法时,如果方法有参数,spring会去容器中查找有没有可用的bean对象,
* 查找的方式和Autowired是一样的。
*/
@Configuration
@ComponentScan(basePackages = "com")
public class SpringConfiguratioin {
@Bean(name="runner")
@Scope(value="prototype") // 可以设置scope
public QueryRunner createQueryRunner(DataSource ds)
{
return new QueryRunner(ds);
}
@Bean(name="ds")
public DataSource createDatasource()
{
ComboPooledDataSource ds = new ComboPooledDataSource();
try
{
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/test");
ds.setUser("root");
ds.setPassword("123456");
return ds;
}catch (Exception e)
{
throw new RuntimeException(e);
}
}
}
删除applicationContext.xml文件,测试使用(testFindAll方法举例):
@Test
public void testFindAll() {
//1.获取容器
// ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguratioin.class);
//2.得到业务对象
UserService usv= (UserService)ac.getBean("userServiceImpl");
List<User> ulist = usv.findAllUsers();
//3.执行方法
for(User us:ulist)
{
System.out.println(us);
}
}
在这里,@Configuration注解可以不写,因为AnnotationConfigApplicationContext(SpringConfiguratioin.class);当前指定的配置加载类就是当前类,如果将配置写到其他的类JdbcConfiguration里,那么需要在JdbcConfiguration的类上面必须加入@Configuration,并且在主配置文件SpringConfiguration中加入JdbcConfiguration的扫描包, 否则不会加载对应的配置,另外不加的话也可以使用(其实和加是一致的意思)AnnotationConfigApplicationContext(SpringConfiguratioin.class,BB.class);
方式1:
调用:
方式2:
方式3:@Import注解
不想在AnnotationConfigApplicationContext中加入JdbcConfiguration.class等配置类的类信息,也不想写扫描包和加@Configuration注解,可以使用@Import实现。
- Import
- 作用:用于导入其他的配置类
- 属性:
-
value:用于指定其他配置类的字节码,
-
当我们使用Import注解之后,有Import注解的类就是父配置类,而导入的类就是子配置类。
- 在JdbcConfiguration配置了数据库信息,但是写在代码里,写死了,因此应该使用配置文件单独拿出来,方便修改。
配置文件存放数据库连接信息
配置信息写入配置文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=123456
最关键的是要让我们定义的@Value读取到properties配置文件中的信息。要使用@PropertySource注解
@PropertySource:
作用:用于指定properties配置文件位置
属性:value,指定文件的名称和文件的路径。关键字:classpath表示类路径下,如果有包,就可以写成比如:
//@PropertySource("classpath:config/spring/jdbcConfig.properties")
// 发现单写上述注解写法有毛病,将无法解析出propertie文件中的值
如果使用上述注解则需要在JdbcConfiguration类文件中加入
@Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDevl()
{
return new PropertySourcesPlaceholderConfigurer();
}
有多个数据源的时候使用@Qualifier()指定数据源,@Qualifier可以放到形参中
@Bean(name="runner")
@Scope(value="prototype") // 可以设置scope
public QueryRunner createQueryRunner(@Qualifier("ds2") DataSource datasource)
{ // 有多个数据源的时候,寻找数据源类似Autowired注解 如果有多个,则用声明的形参去匹配,找名字相同的,找不到就报错。
//需要一种方法,datasource不变化,但是可以切换数据源 @Qualifier("ds1")
return new QueryRunner(datasource);
}
@Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDevl()
{
return new PropertySourcesPlaceholderConfigurer();
}
@Bean(name="ds2")
public DataSource createDatasource()
{
ComboPooledDataSource ds = new ComboPooledDataSource();
try
{
/* ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/test");
ds.setUser("root");
ds.setPassword("123456");*/
ds.setDriverClass(driver);
ds.setJdbcUrl(url);
ds.setUser(username);
ds.setPassword(password);
return ds;
}catch (Exception e)
{
throw new RuntimeException(e);
}
}
@Bean(name="ds1")
public DataSource createDatasource1()
{
ComboPooledDataSource ds = new ComboPooledDataSource();
try
{
ds.setDriverClass(driver);
ds.setJdbcUrl("jdbc:mysql://localhost:3306/mysql45");
ds.setUser(username);
ds.setPassword(password);
return ds;
}catch (Exception e)
{
throw new RuntimeException(e);
}
}
整合spring与Junit
即我们不希望重复出现
// ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguratioin.class);
// UserService usv= (UserService)ac.getBean("userServiceImpl");
而是希望,注解的方式注入UserService,并且自动加载创建容器(解析xml文件或者spring注解配置)
xml方式:
注解方式(图中红色框有点毛病哈,应该是@ContextConfiguration())的内容对比xml方式:
package com.test;
import com.domain.User;
import com.service.UserService;
import config.JdbcConfiguration;
import config.SpringConfiguratioin;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
/**
* 使用Junit测试我们的方法
* spring整合Junit的配置
* 1,导入spring整合junit的jar包 spring-test
* 2,使用Junit提供的一个注解把原来的main方法替换,替换成spirng提供的@RunWith
* 3,告知spring的运行器,spring和ioc创建是基于xml还是注解的,并且说明位置
* @ContextConfiguration
* location:指定xml文件位置,加上classpath关键字,表示在类路径下
* classes:指定注解类所在的位置
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguratioin.class)
public class UserServiceTest {
//private ApplicationContext ac;
@Autowired
private UserService usv;
// @Before
// public void init()
// {
// ac = new AnnotationConfigApplicationContext(SpringConfiguratioin.class);
// usv= (UserService)ac.getBean("userServiceImpl");
// }
@Test
public void testFindAll() {
List<User> ulist = usv.findAllUsers();
//3.执行方法
for(User us:ulist)
{
System.out.println(us);
}
}
@Test
public void testFindOne() {
Integer uid = 8;
User ures = usv.findOneUserById(uid);
System.out.println(ures);
}
@Test
public void testSave() {
User user = new User();
user.setUsername("orange");
user.setPassword("999");
usv.saveUser(user);
}
@Test
public void testUpdate() {
User u = new User();
u.setUid(10);
u.setPassword("123999");
u.setUsername("uuu hr");
usv.updateUserById(u);
}
@Test
public void testDel() {
usv.deleteUserById(12);
}
}