一 、spring IOC & DI
IOC inversion of Controller 控制反转。
由我们自己实例化的对象交给spring容器来实始化。这时对象的初始化的权利就会反转。
DI dependency injection 依赖注入
在spring框架负责创建Bean对象时,动态将依赖对象注入到Bean组件
1.提供User实体类
public interface Person {
void desc();
}
public class User implements Person{
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
@Override
public void desc() { System.out.println("hi~"+name);}
}
2.编写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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="u" class="com.b3a4a.ioc.User">
<!-- 通过依赖注入将cnB3a4a这个值注到实例对象的name属性中 -->
<property name="name" value="cnB3a4a"></property>
</bean>
</beans>
注意:
<bean></bean>标签注意事项
在开发中可以使用id或name
id它遵守xml规范,名称中不能包含特殊符号
name它是为了更好的扩展,在name中可以包含一些特殊符号,例如"_"
3.获取对象实例
@Test
public void test(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Person u = (Person) applicationContext.getBean("u");
u.desc();
}
二、Bean创建&Bean作用范围
Bean工厂结构
BeanFactory(根接口)
ApplicationContext(子接口)
ClassPathXmlApplicationContext
FileSystemXmlApplicationContext
AnnotationConfigApplicationContext
org.springframework.web.context.WebApplicationContext(ApplicationContext的子接口)
BeanFactory和ApplicationContext区别
BeanFactory延时加载(什么时候需要什么时候创建)
ApplicationContext立即加载(加载配置文件时就会创建)
Bean创建的3种方式
A)通过无参数构造来创建
B)通过静态工厂方法来创建
C)通过实例工厂方法来创建
使用spring创建Bean步骤
1.创建接口(IBean)和实现类(IBeanImpl)
public interface IBean {
void desc();
}
public class BeanImpl implements IBean {
@Override
public void desc() {
System.out.println("hello !!!");
}
}
public class StaticBeanFactory {
//------方式二------
//通过通过静态工厂方法来创建
public static BeanImpl createBean(){
return new BeanImpl();
}
}
//------方式三------
//通过实例工厂方法来创建
public class BeansFactory{
public BeanImpl getBean(){
return new BeanImpl();
}
}
2.编写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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--方式一-->
<!--通过无参构造创建bean-->
<bean id="bean" class="com.b3a4a.ioc.BeanImpl"> </bean>
<!--方式二-->
<!--通过静态工厂方法创建bean-->
<bean id="bean" class="com.b3a4a.ioc.StaticBeanFactory" factory-method="createBean"> </bean>
<!--方式三-->
<!--通过工厂方法创建bean-->
<bean id="beanFactory" class="com.b3a4a.ioc.BeansFactory"> </bean>
<bean id="bean" factory-bean="beanFactory" factory-method="getBean"> </bean>
</beans>
3.通过工厂来创建对象
a)通过BeanFactory来获取
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
b)通过ClassPathXmlApplicationContext来获取
ApplicationContext factory = new ClassPathXmlApplicationContext("applicationContext.xml");
IBean bean = (IBean) factory.getBean("bean");
配置Bean的作用域
在applicationContext.xml文件中bean标签上配置scope属性
singleton 单例 代表在spring ioc容器中只有一个Bean实例 (默认的scope)
prototype 多例 每一次从spring容器中获取时,都会返回一个新的实例
request 用在web开发中,将bean对象request.setAttribute()存储到request域中
session 用在web开发中,将bean对象session.setAttribute()存储到session域中
<?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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bean" class="com.b3a4a.ioc.BeanImpl" scope="singleton"> </bean>
</beans>
注意:
作用于为prototype时创建对象为延迟创建 创建对象时
作用于为singleton时创建对象为立即创建 加载容器时
三、SpringBean注入
1、属性注入
1.创建实体类Car和Person
public class Car {
private String name;
private double price;
public Car() {}
public Car(String name, double price) {
this.name = name;
this.price = price;
}
//省略get/set方法
}
public class Person {
private String name;
private Car car;
//省略get/set方法
}
2.配置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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 使用setter方法对car的属性进行注入 -->
<bean id="mCar" class="com.b3a4a.di.Car">
<property name="name" value="宝马" />
<property name="price" value="500000" />
</bean>
<bean name="person" class="com.b3a4a.di.Person">
<property name="name" value="b3a4a" />
<!-- ref引用其它bean的id或name值 -->
<property name="car" ref="mCar" />
</bean>
<!-- 使用构造方法对car的属性进行注入 -->
<bean id="benzCar" class="com.b3a4a.di.Car">
<constructor-arg name="name value="奔弛" />
<constructor-arg name="price" value="1000000" />
</bean>
</beans>
3.获取对象实例
@Test
public void test(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) applicationContext.getBean("person");
System.out.println(person.getName() + " " + person.getCar().getName());
//Car benzCar = (Car)applicationContext.getBean("benzCar")
}
3 、 集合注入
Map、Set、List、数组、属性
1.创建实体类
public class Department {
private String name;
private String [] arr;//数组
private List<Emp> list;//list集合
private Set<Emp> set;//set集合
private Map<String,Emp> map;//map集合
private Properties pp;//Properties的使用
//省略get/set方法
......
}
2.对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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="department" class="com.b3a4a.domain.Department">
<property name="name" value="财务部"/>
<!-- 给数组注入值 -->
<property name="arr">
<list>
<value>小明</value>
<value>小明</value>
</list>
</property>
<!-- 给list注入值 list 中可以有相当的对象 -->
<property name="list">
<list>
<ref bean="emp2" />
<ref bean="emp1"/>
</list>
</property>
<!-- 给set注入值 set不能有相同的对象 -->
<property name="set">
<set>
<ref bean="emp1" />
<ref bean="emp2"/>
</set>
</property>
<!-- 给map注入值 map只有key不一样,就可以装配value -->
<property name="map">
<map>
<entry key="11" value-ref="emp1" />
<entry key="22" value-ref="emp2"/>
<entry key="22" value-ref="emp1"/>
</map>
</property>
<!-- 给属性集合配置 -->
<property name="pp">
<props>
<prop key="pp1">abcd</prop>
<prop key="pp2">hello</prop>
</props>
</property>
</bean>
<bean id="emp1" class="com.b3a4a.domain.Emp">
<property name="name" value="北京"/>
<property name="id" value="1"/>
</bean>
<bean id="emp2" class="com.b3a4a.domain.Emp">
<property name="name" value="天津"/>
<property name="id" value="2"/>
</bean>
</beans>
3.通过api获取对应属性
public void test(){
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
Department department=(Department) ac.getBean("department");
arr/list/set/map/pp = department.getXXX();
//遍历
}
四 Spring 、注解开发
1.导入相应jar包
spring-beans-4.2.4.RELEASE.jar
spring-context-4.2.4.RELEASE.jar
spring-core-4.2.4.RELEASE.jar
spring-expression-4.2.4.RELEASE.jar
commons-logging-1.2.jar
log4j-1.2.16.jar
注意:
spring-aop-4.2.4.RELEASE.jar
2.配置applicationContext.xml(需要在schema约束中引入context命名空间)
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.b3a4a" />
</beans>
3.在类中使用注解
@Component("loginService")
@Scope("prototype")
public class LoginServiceIMPL implements LoginService {
@Value("cnB3a4a")
private String username;
//@Autowired //默认是按照类型来进行注入
//@Qualifier("userDao")
@Resource(name="userDao")
private UserDAO userDao;
@Override
public void add() {
// System.out.println("userService add.." + name);
userDao.add();
}
@PostConstruct
public void mInit(){}
@PreDestory
public void mDestory(){}
}
注意:
如果将注入属性的注解配置在属性上,则可以省略get/set方法
解释说明:
a) @Component
相当于 <bean id="loginService" class="com.b3a4a.annotationtest.LoginServiceIMPL">
@Component有三个衍生注解功能一样,只是对作用位置进行区分
@Repository 用于DAO层
@Service 用于service层
@Controller 用于表现层
b) @Value 非引用类型
相当于<property name="username" value="cnB3a4a" />
c) @Autowired @Qualifier 引用类型
@Autowired 自动装配对象(类型)
@Qualifier 装配指定名称对象
@Primary 提高java优先级
d) @Resource(name="名字")
相当于@Autowired和@Qualifier一起配置
e) @Scope
相当于 <bean id="loginService" class="com.b3a4a.annotationtest.LoginServiceIMPL" scope="singleton"> </bean>
@Scope取值有4个
singleton 单例 代表在spring ioc容器中只有一个Bean实例 (默认的scope)
prototype 多例 每一次从spring容器中获取时,都会返回一个新的实例
request 用在web开发中,将bean对象request.setAttribute()存储到request域中
session 用在web开发中,将bean对象session.setAttribute()存储到session域中
f) @PostConstruct
相当于 <bean id="loginService" class="com.b3a4a.annotationtest.LoginServiceIMPL" init-method="mInit" > </bean>
@PostConstruct注解好多人以为是Spring提供的。其实是Java自己的注解。
Java中该注解的说明:@PostConstruct该注解被用来修饰一个非静态的void()方法。被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。
通常我们会是在Spring框架中使用到@PostConstruct注解 该注解的方法在整个Bean初始化中的执行顺序:
Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
g) @PreDestory
相当与 <bean id="loginService" class="com.b3a4a.annotationtest.LoginServiceIMPL" destory-method="mDestory" > </bean>
注意:对于销毁的方法它只对bean的scope=singleton有效。
@PreDestory修饰的方法会在服务器卸载Servlet的时候运行,并且之后被服务器调用一次,类似于Servlet 中的destory()方法,虽然PreDestory字面意思是在destory之前运行,但是被@PreDestory修饰的方法会在destory方法运行之后运行,在Servlet被彻底卸载之前,PreDestory里的Destory指的是Servlet的销毁,而不是destory()方法。
依赖加载
@DependsOn 两个Bean的加载顺序
@Order 配置文件加载顺序 1 2 3
@Lazy 类 方法 延迟加载 灾难恢复
5、 Spring全注解配置
配置流程
主配置文件SpringConfiguration
@Configuration //主配置文件
@ComponentScan("com.b3a4a") //扫描包
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbcConfig.properties") //加载properties
public class SpringConfiguration {
}
辅配置文件JdbcConfig
public class JdbcConfig {
@Value("${jdbc.driver}")private String driver;
@Value("${jdbc.url}")private String url;
@Value("${jdbc.username}")private String username;
@Value("${jdbc.password}")private String password;
@Bean(name="runner")
@Scope("prototype")
public QueryRunner createQueryRunner(@Qualifier("mysql_ds") DataSource dataSource){
return new QueryRunner(dataSource);
}
@Bean(name="mysql_ds")
public DataSource createMysqlDataSource(){
try {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass(driver);
ds.setJdbcUrl(url);
ds.setUser(username);
ds.setPassword(password);
return ds;
}catch (Exception e){
throw new RuntimeException(e);
}
}
@Bean(name="oracle_ds")
public DataSource createOracleDataSource(){
return null;
}
}
测试用例
@Test
public void testFindAllUsers() {
//1.获取容易
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
//2.得到业务层对象
UserService service = ac.getBean(UserService.class);
//3.执行方法
List<User> users = service.findAllUsers();
for (User user : users) {
System.out.println(user);
}
}