Spring框架(原理探索)分为两个部分:
-
Spring框架之IOC容器概述
-
用配置文件和完全注解方式探索Spring中AOP
(一)Spring框架之IOC容器概述
IOC的底层原理
XML解析、工厂模式、反射
什么是IOC
-
控制反转,把对象创建和对象之间的调用过程交给Spring进行管理
-
使用IOC的目的:为了降低耦合度
-
做入门案例就是IOC实现
IOC接口(BeanFactory)
IOC操作Bean管理(基于XML)
IOC操作Bean管理(基于注解)
开始步骤
1.新建Java项目,将Spring一下的jar包进行导入
commons-logging-1.2.jar
spring-context-5.3.20.jar
spring-beans-5.3.20.jar
spring-expression-5.3.20.jar
spring-core-5.3.20.jar
2.新建User对象
class User{
public void Add(){
System.out.println("add-------------");
}
}
3.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">
<!--配置User对象的创建-->
<bean id="user" class="com.company.User"></bean>
</beans>
4.进行测试代码编写
package com.company.TestDemo;
import com.company.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestDemo {
@Test
public void Test(){
// 加载配置文件
ApplicationContext context=new ClassPathXmlApplicationContext("com/company/bean1.xml");
//获取配置创建的对象
User user = context.getBean("user", User.class);
System.out.println(user);
user.Add();
}
}
IOC的过程(解决对象创建和对象之间调用的耦合度问题)
<bean id="user" class="com.company.User"></bean>
public class IOC{
public static UserDao getDao(){
String classValue= "com.company.User";//获取xml中包名
Class clazz=Class.forName(classValue);//通过报名获取该类字节码
return clazz.newInstance();//通过newInstance对该类进行实例化
}
}
IOC接口
IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
Spring提供IOC容器实现两种方式:
1.BeanFactory: IOC容器基本的实现,是Spring内部的使用接口,不提供开发人员进行使用
加载配置获取的时候不会创建对象,在获取对象(getBean)或使用对象时候后才进行创建对象
2.ApplicationContext: BeanFactory接口的子接口,提供更对更强大的功能,一般有开发人员进行使用 加载配置文件的时候就进行对象创建
IOC操作Bean管理
什么是Bean管理
Spring创建对象
Spring注入属性
Bean管理操作有两种方式
(A)基于xml配置文件方式实现
在spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象的创建
在bean标签里里面有很多属性,介绍常用的属性(id="唯一标识",class="包路径")
(1) 使用set方法进行属性赋值
<bean id="user" class="com.company.User">
<property name="name" value="张三"></property>
<property name="sex" value="20"></property>
</bean>
或则使用p标签进行注入(添加:
xmlns:p="http://www.springframework.org/schema/p")
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user_p" class="com.company.User" p:name="李四" p:sex="23"></bean>
</beans>
(2) 使用有参构造方法注入
<bean id="book" class="com.company.Book">
<constructor-arg name="bname" value="高数"></constructor-arg>
<constructor-arg name="price" value="70"></constructor-arg>
</bean>
(3) 注入对象方式
<bean id="UserDao" class="com.company.dao.UserDao"></bean>
<bean id="UserServiceImpl" class="com.company.service.UserServiceImpl">
<property name="userDaoInfo" ref="UserDao"></property>
</bean>
(4) 注入数组/List/Map/Set & 外部Bean/内部Bean & 提取List(Util)方式
<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<util:list id="UtilList">
<value>s</value>
<value>m</value>
<value>c</value>
<value>w</value>
</util:list>
<bean id="UserDao" class="com.company.dao.UserDao">
<property name="name" value="wei"></property>
<property name="password" value="wei"></property>
</bean>
<bean id="UserDao1" class="com.company.dao.UserDao">
<property name="name" value="min"></property>
<property name="password" value="minpassword"></property>
</bean>
<bean id="UserServiceImpl" class="com.company.service.UserServiceImpl">
<property name="userDaoInfo" ref="UserDao"></property>
<property name="list1" ref="UtilList"></property>
<property name="strings">
<list>
<value>chen</value>
<value>qi</value>
<value>wei</value>
</list>
</property>
<property name="list">
<list>
<ref bean="UserDao"></ref>
<ref bean="UserDao1"></ref>
</list>
</property>
<property name="map">
<map>
<entry key="s" value="chen"></entry>
<entry key="m" value="qiwei"></entry>
</map>
</property>
<property name="sets">
<set>
<value>234</value>
<value>456</value>
<value>789</value>
</set>
</property>
</bean>
</beans>
bean管理的特殊情况处理方法
设置默认null值
<bean id="user" class="com.company.User">
<property name="name" value="张三"></property>
<property name="sex" value="20"></property>
<property name="cite">
<null/>
</property>
</bean>
设置特殊字符(设置默认属性值:<<北京>>)
方式一:设置为:value=“<<北京>>”
<bean id="user" class="com.company.User">
<property name="name" value="张三"></property>
<property name="sex" value="20"></property>
<property name="cite" value="<<北京>>"></property>
</bean>
方式二:特殊内容写到CDATA中去
<bean id="user" class="com.company.User">
<property name="name" value="张三"></property>
<property name="sex" value="20"></property>
<property name="cite">
<value>
<![CDATA[<<北京>>]]>
</value>
</property>
</bean>
IOC操作Bean管理
1.Spring有两种bean,一种普通bean,另外一种工厂bean(FactoryBean)
2.普通bean:在配置文件中定义bean类型就是返回类型
3.工厂bean:在配置文件定义bean类型可以和返回类型不一样(实现FactoryBean的getObject()方法就行)
如何设置单实例还是多实例
1.在bean标签中设置scopy属性设置:
(1) scopy="singleton",表示单实例对象(加载配置文件就创建对象)
(2) scopy="prototype",表示多实例对象(加载配置文件不创建对象,调用获取对象才创建对象)
IOC操作Bean管理(bean的生命周期)
1.生命周期
从对象创建到对象的销毁的过程
2.bean生命周期
(1) 通过构造器创建bean实例 (无参数构造)
(2) 为bean的属性设置属性值和对其他的bean引用(调用set方法)
(3) 把bean示例对象传递bean后置处理器的方法(postProcessBeforeInitialization)
(4) 调用bean的初始化的方法(需要进行配置初始化的方法)
(5) 把bean示例对象传递bean后置处理器的方法(postProcessAfterInitialization)
(6) bean可以使用了(对象获取到了)
(7) 当容器关闭时候,调用bean的销毁的方法(需要及进行配置销毁的方法)
3.代码示例
1.实体类的定义
package com.company;
public class Book {//实体类的定义
private String bname;
private String price;
public void setBname(String bname) {
System.out.println("第二步为bean对象设置属性值或引用外部bean");
this.bname = bname;
}
public void setPrice(String price) {
this.price = price;
}
public Book() {
System.out.println("第一步通过无参构造方法创建bean对象");
}
public Book(String bname, String price) {
this.bname = bname;
this.price = price;
}
public void SeeBook(){
System.out.println(bname+"::"+price);
}
public void initMethod(){
System.out.println("第三步调用初始化方法");
}
public void destroyMethod(){
System.out.println("第五步调用销毁方法!");
}
}
相关xml定义
<bean id="book" class="com.company.Book" init-method="initMethod" destroy-method="destroyMethod">
<property name="bname" value="sun"></property>
<property name="price" value="qwe"></property>
</bean>
测试方法
public class TestDemo {
@Test
public void Test(){
// 加载配置文件
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("com/company/bean1.xml");
//获取配置创建的对象
Book book=context.getBean("book",Book.class);
System.out.println("第四步获取对象");
book.SeeBook();
context.close();//手动销毁
}
}
运行结果
第一步通过无参构造方法创建bean对象
第二步为bean对象设置属性值或引用外部bean
在初始化之前执行的方法
第三步调用初始化方法
在初始化之后的执行方法
第四步获取对象
sun::qwe
第五步调用销毁方法!
IOC生命周期后置处理器
public class MyBean implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之前执行的方法");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之后的执行方法");
return bean;
}
}
<!-- 添加后置处理器-->
<bean id="myBean" class="com.company.MyBean"></bean>
IOC的自动装配
什么是自动装配
(1) 根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入
bean标签属性autowire(byName/byType),配置自动装配。
<bean id="book" class="com.company.Book" init-method="initMethod" destroy-method="destroyMethod" autowire="byName">
</bean>
(2) 外部文件实现自动装配
<?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:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
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/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/util/spring-context.xsd">
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${cqw.driverClassName}"></property>
<property name="url" value="${cqw.url}"></property>
<property name="username" value="${cqw.userName}"></property>
<property name="password" value="${cqw.password}"></property>
</bean>
<!-- 引入外部文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
</beans>
IOC操作Bean管理(基于注解方式)
注解(@注解名),可以作用于类,方法及属性上添加,极其简化xml配置
Spring针对Bean管理中创建对象提供注解(以下都可以创建对象)
@Component
@Service
@Controller
@Repository
基于注解方式实现对象创建
1.引入依赖(spring-aop-5.3.20.jar)
2.开启组件扫描
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
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/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.company">
<!-- 注解不包含扫描-->
<!-- <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>-->
<!-- 注解包含扫描-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
</beans>
基于注解方式实现属性创建
@AutoWired : 根据属性类型进行自动装配
@Autowiredprivate MinDao minDao;
@Qualifier : 根据属性名称进行注入(调用接口指定其实现类名称)
@Autowired@Qualifier(value = "minDaoImpl1")private MinDao minDao;
@Resource : 可以根据类型注入,可以根据名称注入
@Resource(name = "minDaoImpl1")private MinDao minDao;
@Value :注入普通类型属性
@Value(value="abc")private String name;
(B)纯注解开发
定义config类并注解@Configuration @ComponentScan
package com.company.Config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = {"com.company"})
public class Config {
}
测试调用修改
public class TestDemo {
@Test
public void Test() throws SQLException {
// 加载配置文件
ApplicationContext context=new AnnotationConfigApplicationContext(Config.class);//参数为刚创建的类
//获取配置创建的对象
MinServiceImpl minService = context.getBean("minServiceImpl", MinServiceImpl.class);
minService.Add();
}
}