Spring框架的几个核心概念:
- IoC:Inversion of Control,控制反转(对象创建的控制权转交给了Spring)
- DI:Dependency Injection,依赖注入
- AOP:Aspect Orientend Programming,面向切面编程
一、没有IoC,都需要手动创建并引入相关的对象实例,结构如下:
- 创建factory.properties文件里面配置相关的类
- 创建工厂类,工厂类加载配置文件,然后实例化返回相关需要的对象
二、 引入Spring的IoC之后:
- 不需要手动创建对象进行引用。Spring会根据约定的配置自动创建对象。其实就是充当工厂方法进行解藕,导入logback-classic框架后能看到更多的细节。
- 首先要配置一个Spring的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="personDao" class="com.mj.dao.impl.PersonDaoImpl"/>
<bean id="personService" class="com.mj.service.impl.PersonServiceImpl">
<property name="dao" ref="personDao"/>
</bean>
<bean id="personServlet" class="com.mj.servlet.PersonServlet">
<property name="service" ref="personService"/>
</bean>
</beans>
- 然后需要设置service和dao的set方法,上面配置文件是根据set方法进行赋值操作。
public class PersonServlet { // PersonService service = PersonFactory.getService(); PersonService service; public void setService(PersonService service) { this.service = service; } private void remove(){ service.remove(1); } public static void main(String[] args) { // 读取配置文件 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); PersonServlet servlet = ctx.getBean("personServlet",PersonServlet.class); servlet.remove(); } }
三、依赖注入
常用的注入内容可以分为以下三种类型
- bean自定义类型
- 基本类型:String、Interger等
- 集合类型(数组、Map、List、Set、Properties)
常见的注入方式有两种
- 基于setter(属性)
- 基于构造方法
set方法注入:
<bean id="personServlet" class="com.mj.servlet.PersonServlet">
<property name="service" ref="personService"/>
</bean>
public class PersonServlet {
PersonService service;
public void setService(PersonService service) {
this.service = service;
}
}
以上就是依赖注入,servlet依赖sevice,配置好之后自动注入。
以下的注入是同一只狗对象:
<bean id="dog" class="com.mj.domain.Dog"/>
<bean id="person" class="com.mj.domain.Person">
<property name="name" value="小马哥"/>
<property name="age" value="12"/>
<property name="dog" ref="dog"/>
</bean>
<bean id="student" class="com.mj.domain.Student">
<property name="dog" ref="dog"/>
</bean>
以下注入是不同的狗对象:
<bean id="person" class="com.mj.domain.Person">
<property name="dog">
<bean class="com.mj.domain.Dog"/>
</property>
</bean>
<bean id="student" class="com.mj.domain.Student">
<property name="dog">
<bean class="com.mj.domain.Dog"/>
</property>
</bean>
以下是字符串数组的注入:
<bean id="person" class="com.mj.domain.Person">
<property name="name" value="小马哥"/>
<property name="age" value="12"/>
<property name="dog">
<bean class="com.mj.domain.Dog"/>
</property>
<property name="nickNames" >
<array>
<value>damage</value>
<value>小马哥</value>
<value>大神</value>
</array>
</property>
<property name="maps">
<map>
<entry key="key1" value="value1"/>
<entry key="key2" value="value2"/>
<entry key="key3" value="value3"/>
</map>
</property>
</bean>
构造方法注入:
<bean id="person" class="com.mj.domain.Person">
<constructor-arg index="0" value="18"/>
<constructor-arg index="1" value="我是小马哥"/>
<constructor-arg>
<bean class="com.mj.domain.Dog"/>
</constructor-arg>
</bean>
方法注入:
factory:
public class ConnectionFactory {
public static Connection getConn() throws Exception {
// Class.forName("com.mysql.cj.jdbc.Driver");
return DriverManager.getConnection("jdbc:mysql://localhost:3306/crm","root","123456");
}
public Connection getInstanceConn() throws Exception {
return DriverManager.getConnection("jdbc:mysql://localhost:3306/crm","root","123456");
}
}
applicationContext.xml文件:
<!-- 静态工厂方法(调用ConnectionFactory,getConn()) -->
<bean id="conn" class="com.mj.obj.ConnectionFactory" factory-method="getConn"/>
<!--实例工厂方法-->
<bean id="factory" class="com.mj.obj.ConnectionFactory">
<property name="dirverClass" value="xxxx"/>
<property name="password" value="xxx"/>
<property name="username" value="xxx"/>
<property name="url" value="xxx"/>
</bean>
<bean id="instanceConn" factory-bean="factory" factory-method="getInstanceConn"/>
测试类:
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println(context.getBean("conn"));
System.out.println(context.getBean("instanceConn"));
}
scope
可以通过scope属性控制bean是否单例
- singleton:单例;通过同一个id值,在一个IoC容器中获取的永远是同一个实例;在IoC容器创建的时候,就会创建bean,可以设置lazy-init为true修改创建时机
- prototype:非单例,每次getBean时创建一次bean
<bean id="dog" class="com.mj.domain.Dog" scope="singleton" lazy-init="true"/>
注意username保留字段:
转换器:
内置的转换器可以完成部分功能,比如下面日期只能用2011/09/23这种类型,如果用2011-09-23就会报错,这时候需要我们自定义转换器
<bean id="person" class="com.mj.domain.Person">
<property name="date" value="2011/05/30"/>
</bean>
编写转换类:
package com.mj.converter;
import org.springframework.core.convert.converter.Converter;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateConverter implements Converter<String, Date> {
private String format;
public void setFormat(String format) {
this.format = format;
}
public Date convert(String s) {
SimpleDateFormat fmt = new SimpleDateFormat(format);
try {
return fmt.parse(s);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
xml文件配置:
注意细节:配置FactoryBean时的 id要固定为conversionService
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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="person" class="com.mj.domain.Person" p:date="09_10_2010"/>
<!--配置FactoryBean id要固定为conversionService-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.mj.converter.DateConverter" p:format="yyyy-MM-dd"/>
<bean class="com.mj.converter.DateConverter" p:format="MM_dd_yyyy"/>
</set>
</property>
</bean>
</beans>