目录
程序的耦合和解耦
传统的MVC模式
使用工厂模式进行解耦
Spring IOC原理
Spring的IOC解决方法
简单搭建spring-maven环境
获取容器的方法
bean标签
实例化Bean的三种方式
依赖注入
构造方法注入
set注入
注入集合
Spring是全栈轻量级开源框架,它的核心是AOP、IOC.
逻辑层依赖于持久层;表现层依赖于逻辑层,所以这种耦合程度太高了
还存在编译期报错的情况,因为对象全是new出来的。编译期异常:当没有导入该jar包时就会报出该异常。
思路:
/** * JavaBean工厂类 读取配置文件,通过读取到的全限定类名创建对象,并且将其存储到map中 */ public class beanfactory { private static Properties properties; private static Map beans; static { try { beans=new HashMap<String,Object>(); properties=new Properties(); InputStream asStream = beanfactory.class.getClassLoader().getResourceAsStream("bean.properties"); properties.load(asStream); Enumeration<Object> keys = properties.keys(); while (keys.hasMoreElements()){ String key=keys.nextElement().toString(); Object object=Class.forName(properties.getProperty(key)).newInstance(); beans.put(key,object); } } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } } public static Object getBean(String className){ return beans.get(className); } } /** * service的实现类 * 通过使用JavaBean工厂类进行解耦 */ public class serviceimpl implements Iservice { Idao idao=(daoimpl)beanfactory.getBean("daoimpl"); @Override public void Sadd() { idao.add(); } } /** * web层 创建serviceimpl对象的方法 与上方相同 */
将JavaBean对象的控制权交给工厂,实现了控制反转
Maven工厂导入坐标
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.0.5.RELEASE</version> </dependency>
编写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="service" class="dome1.service.impl.serviceimpl"></bean> </beans>
测试代码
public static void main(String[] args) { //获取容器对象 ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); //从容器中取走对象 serviceimpl service = (serviceimpl) context.getBean("service"); System.out.println(service);//dome1.service.impl.serviceimpl@7d9d1a19 }
ApplicationContext与BeanFactory的区别
BeanFactory是Spring容器的顶层接口,创建对象的时机:什么时候使用什么时候创建对象(适合多例)
ApplicationContext:创建对象的时机是只要读取配置文件,就创建对象(适合单例对象)
public static void main(String[] args) { //单例对象 ApplicationContext context1 = new ClassPathXmlApplicationContext("bean.xml"); Object service = context1.getBean("service"); //多例对象 ClassPathResource resource = new ClassPathResource("bean.xml"); BeanFactory beanFactory = new XmlBeanFactory(resource); Object service1 = beanFactory.getBean("service"); }
属性
有关生命周期的属性
示例代码:bean的生命周期
bean配置
<bean id="service" class="dome1.service.impl.serviceimpl" init-method="init" destroy-method="display">
测试代码
public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); Object service = context.getBean("service"); context.close();//手动关掉容器 }
控制台输出
单例对象:与容器相关,创建容器的同时对象就会被创建,销毁容器时对象就会被销毁。
多例对象:当使用对象时才会被创建,只要对象在使用,就一直活着;当对象长时间不用时,就会被java的垃圾回收器回收了
<?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="dome1" class="dome1.service1.dome1"/> <!-- 实例工厂(两步):先将工厂对象放进spring 在从方法中获取对象--> <bean id="dome2" class="dome1.service1.dome2"/> <bean id="dome21" factory-bean="dome2" factory-method="getDome1"/> <!-- 静态工厂 直接调用方法获取对象--> <bean id="dome3" class="dome1.service1.dome3" factory-method="getDome"/> </beans>
bean标签内使用constructor标签
属性
优点:在获取bean对象时,注入数据是必须的操作,否则无法创建成功
缺点:如果用不到这些数据也必须创建
bean标签内使用property标签
属性
优点:创建对象时没有明确的限制,可以直接使用默认构造方法
缺点:如果要求某个变量必须有值,这种方法无法保证必须有值,例如:没有调用set方法等等
<!-- 有参构造 构造方法的注入--> <bean id="now" class="java.util.Date"/> <bean id="dome11" class="dome1.service1.dome1"> <constructor-arg name="string" value="张三"/> <constructor-arg type="java.lang.Integer" value="123"/> <constructor-arg index="2" ref="now"/> </bean> <!-- set注入--> <bean id="dome12" class="dome1.service1.dome1"> <property name="string" value="李四"/> <property name="date" ref="now"/> <property name="integer" value="12"/> </bean>
本质:就是set注入
用于给list结构注入的标签:list、set、array
用于给map结构注入的标签:map、props
同一结构的标签可以互换
<!-- 注入集合--> <bean id="dome4" class="dome1.service1.dome4"> <!-- 数组--> <property name="strings"> <array> <value>AAA</value> <value>BBB</value> </array> </property> <!-- list--> <property name="list"> <list> <value>CCC</value> <value>SSS</value> </list> </property> <!-- set--> <property name="set"> <set> <value>WWW</value> <value>AAA</value> </set> </property> <!-- map--> <property name="map"> <map> <entry key="AAA" value="BBBB"/> <entry key="BBB" value="CCC"/> </map> </property> <!-- pro--> <property name="properties"> <props> <prop key="AAA">BBB</prop> <prop key="WWW">CCC</prop> </props> </property> </bean>