spring学习笔记
spring核心部分:IOC AOP
IOC: (Inversion of Control,IOC)控制反转,把创建对象的过程交给spring进行管理(通常称为Bean),通过配置文件或注解,你可以指定Bean的创建方式、依赖关系等
AOP: (Aspect-Oriented Programming,AOP)面向切面,不修改源代码进行功能增强,通过配置或注解,你可以将切面与目标对象(被通知的对象)关联起来,当目标对象的方法被调用时,Spring会自动应用相应的切面逻辑
spring提供IOC容器实现两种方式:(两个接口)
1)BeanFactory:IOC容器的基本实现,是spring内部使用的接口
1)BeanFactory:IOC容器的基本实现,是spring内部使用的接口
特点:加载配置文件的时候不会创建对象,在获取对象的时候才去创建对象
2)ApplicationContext:BeanFactory的子接口,提供更多更强大的功能,一般由开发人员使用
特点:加载配置文件时就会把再配置文件对象进行创建
ApplicationContext主要实现类
bean管理
1)spring创建对象
2)spring注入属性
bean管理操作实现方式
1)基于xml配置文件方式实现
2) 基于注解方式实现
配置文件:
<bean>标签
id属性:在容器中Bean实例的唯一标识,不允许重复
class属性:要实例化的Bean的全限定名
scope属性 sean的作用范围,常用是Singleton(默认)和prototype
<property>标签:属性注入
name属性:属性名称
value属性:注入的普通属性值
ref属性:注入的对象引用值
<list>标签
<map>标签
<properties>标签
<constructor-arg>标签
IOC操作bean管理
<import>标签:导入其他的Spring的分文件
1)在spring配置文件中,使用bean标签,标签里面添加对应属性
id属性:唯一标识
classs属性:类全路径
name属性:
<!-- <bean class="com.josie.dao.UserDao" name="userDao"></bean>-->
创建对象的时候,默认也是执行无参数构造方法
2)基于xml方式注入属性
DI:依赖注入,就是注入属性
第一种:使用set注入
在spring配置文件中配置对象创建,配置属性注入
第二种:使用有参数的构造进行注入
package com.testdemo; public class Orders { private String oname; private String address; //有参数构造 public Orders(String oname,String address){ this.oname=oname; this.address=address; } public void orderTest(){ System.out.println(oname+"::"+address); } }
import com.testdemo.Orders; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestOrders { public static void main(String[] args) { //依赖spring注入,从spring的容器中获取orders ApplicationContext ioc = new ClassPathXmlApplicationContext("bean.xml"); Orders orders= ioc.getBean("orders", Orders.class); orders.orderTest(); } }
<?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="orders" class="com.testdemo.Orders"> <constructor-arg name="oname" value="abc"/> <constructor-arg name="address" value="China"/> </bean> </beans>
xml注入其他类型属性
字面量(赋了固定值的变量)
1)null值
<property name="address"> <null/></property>
2)属性值包含特殊符号
<!--属性值包含特殊符号--><property name="address"> <value><![CDATA[<<南京>>]]></value></property>
运行输出 <<南京>>
注入属性-外部bean
1)创建service类和dao类
package com.josie.dao; public class UserDaoImpl implements UserDao{ @Override public void update(){ System.out.println("dao update"); } }
2)在service调用dao里面的方法
package com.josie.service; import com.josie.dao.UserDao; import com.josie.dao.UserDaoImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; public class UserService implements IUserService{ //原始方法UserDao userDao = new UserDaoImpl(); private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void getUser() { System.out.println("user service....."); userDao.update(); } }
<?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"> <!--services和dao对象的创建--> <bean id="userService" class="com.josie.service.UserService"> <!--注入userDao对象 name属性值:类里面属性名称 ref属性:创建userDao对象bean标签id值 --> <property name="userDao" ref="userDaoImpl"></property> </bean> <bean id="userDaoImpl" class="com.josie.dao.UserDaoImpl"></bean> </beans>
注入属性-内部bean和级联赋值
1)一对多的关系:部门和员工
一个部门有多个员工,一个员工属于一个部门,部门是一,员工是多
2)在实体类之间表示一对多关系,员工所属部门用对象类型属性进行表示
3)在spring配置文件中进行配置
package com.bean; public class Emp { private String ename; public String gender; //员工属于某一个部门,使用对象形式表示 private Dept dept; public void setDept(Dept dept) { this.dept = dept; } public void setGender(String gender) { this.gender = gender; } public void setEname(String ename) { this.ename = ename; } public void add(){ System.out.println(ename+"::"+gender+"::"+dept); } }
package com.bean; public class Dept { private String dname; public void setDname(String dname) { this.dname = dname; } @Override public String toString() { return "Dept{" + "dname='" + dname + '\'' + '}'; } }
<?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="emp" class="com.bean.Emp"> <!--设置2个普通属性--> <property name="ename" value="lucky"></property> <property name="gender" value="女"></property> <!--设置对象类型属性--> <property name="dept"> <bean id="dept" class="com.bean.Dept"> <property name="dname" value="安保部"></property> </bean> </property> </bean> </beans>
级联赋值
<?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="emp" class="com.bean.Emp"> <!--设置2个普通属性--> <property name="ename" value="lucky"></property> <property name="gender" value="女"></property> <!--级联赋值--> <property name="dept" ref="dept"></property> </bean> <bean id="dept" class="com.bean.Dept"> <property name="dname" value="财务部"></property> </bean> </beans>
xml注入集合属性
1)注入数组类型属性
2)注入list集合类型属性
3)注入map集合类型属性
创建类,定义属性
package com.demo1; import java.util.List; import java.util.Map; import java.util.Set; public class Stu { //数组类型的属性 private String[] courses; //list集合类型属性 private List<String> list; //map类型属性 private Map<String,String> maps; //set集合类型属性 private Set<String> sets; public String[] getCourses() { return courses; } public List<String> getList() { return list; } public Map<String, String> getMaps() { return maps; } public void setSets(Set<String> sets) { this.sets = sets; } }
在spring配置文件中进行配置
<?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="stu" class="com.demo1.Stu"> <!--数组类型属性的注入--> <property name="courses"> <array> <value>java课程</value> <value>Python课程</value> </array> </property> <!--list类型属性的注入--> <property name="list"> <list> <value>张三</value> <value>小三</value> </list> </property> <!--map类型属性的注入--> <property name="map"> <map> <entry key="Java" value="java"></entry> <entry key="Python" value="python"></entry> </map> </property> <!--set类型属性的注入--> <property name="sets"> <set> <value>MySQL</value> <value>Redis</value> </set> </property> </bean> </beans>
test方法
package com.testDemo1; import com.demo1.Stu; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Testdemo1 { @Test public void testCollection(){ ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); Stu stu = context.getBean("stu", Stu.class); stu.test(); } }
在集合里面设置对象类型属性
package com.demo1; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; public class Stu { public void setCourses(String[] courses) { this.courses = courses; } //数组类型的属性 private String[] courses; public void setList(List<String> list) { this.list = list; } public void setMaps(Map<String, String> maps) { this.maps = maps; } public void setSets(Set<String> sets) { this.sets = sets; } //list集合类型属性 private List<String> list; //map类型属性 private Map<String,String> maps; //set集合类型属性 private Set<String> sets; public void setCourseList(List<Course> courseList) { this.courseList = courseList; } //学生所学的多门课程 private List<Course> courseList; public void test(){ System.out.println(Arrays.toString(courses)); System.out.println(list); System.out.println(maps); System.out.println(sets); } }
package com.demo1; public class Course { @Override public String toString() { return "Course{" + "cname='" + cname + '\'' + '}'; } public void setCname(String cname) { this.cname = cname; } private String cname; }
<?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="stu" class="com.demo1.Stu"> <!--数组类型属性的注入--> <property name="courses"> <array> <value>java课程</value> <value>Python课程</value> </array> </property> <!--list类型属性的注入--> <property name="list"> <list> <value>张三</value> <value>小三</value> </list> </property> <!--map类型属性的注入--> <property name="maps"> <map> <entry key="Java" value="java"></entry> <entry key="Python" value="python"></entry> </map> </property> <!--set类型属性的注入--> <property name="sets"> <set> <value>MySQL</value> <value>Redis</value> </set> </property> <!--注入list集合类型,值是对象类型--> <property name="courseList"> <list> <ref bean="course1"></ref> <ref bean="course2"></ref> </list> </property> </bean> <!--创建多个对象属性值--> <bean id="course1" class="com.demo1.Course"> <property name="cname" value="Spring框架"></property> </bean> <bean id="course2" class="com.demo1.Course"> <property name="cname" value="MyBetis框架"></property> </bean> </beans>
把集合注入部门提取出来
在spring配置文件中引入名称空间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/beans/spring-util.xsd"> <!--集合类型属性的注入--> </beans>
使用util标签完成list集合注入提取
<!--提取list集合类型属性的注入--> <util:list id="bookList"> <value>易筋经</value> <value>西游记</value> </util:list> <!--提取list集合类型属性注入使用--> <bean id="book" class="com.demo1.Book"> <property name="list" ref="bookList"></property> </bean>
package com.demo1; import java.util.List; public class Book { private List<String> list; public void setList(List<String> list) { this.list = list; } public void test(){ System.out.println(list); } }
IOC操作Bean管理(FactoryBean)
1.spring有两种bean,一种普通bean,一种工厂bean(FactoryBean)
2.普通bean:在配置文件中定义的bean类型就是返回的类型
3.工厂bean,在配置文件中定义的bean类型可以和返回的类型不一样
1)创建类,让这个类作为工厂bean,实现接口factory bean
2)实现接口里面的方法,在实现的方法中定义返回的bean类型
package com.factorybean; import com.demo1.Course; import org.springframework.beans.factory.FactoryBean; public class MyBean implements FactoryBean<Course> { @Override public Course getObject() throws Exception { //定义返回bean Course course = new Course(); course.setCname("josie"); return course; } @Override public Class<?> getObjectType() { return null; } }
@Test public void test3(){ ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml"); Course course = context.getBean("myBean", Course.class); System.out.println(course); } }
<?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"> <!--提取list集合类型属性注入使用--> <bean id="myBean" class="com.factorybean.MyBean"> </bean> </beans>
配置文件中定义的类型是MyBean,返回的是Course类型
IOC操作Bean管理(bean作用域)
1、在spring里面,设置创建bean实例是单实例还是多实例
2、在spring里面,在默认情况下bean是一个单实例对象
输出的地址一样,说明是单实例
3、如何设置单实例还是多实例
1)在spring配置文件bean标签里面有属性scope用于设置单实例还是多实例
2)scope属性值
a.默认值,singleton,表示是单实例对象
b.prototype, 表示是多实例对象
3)singleton和prototype区别
a.设置scope值是singleton时候,加载spring配置文件时候就会创建单实例对象
b.设置scope值是prototype时候,不是加载spring配置文件时候创建对象,在调用getBean方法时候创建多实例对象
IOC操作bean管理(生命周期)
package com.bean; public class Orders { //无参构造 public Orders(){ System.out.println("第一步,执行无参数构造创建bean实例"); } public void setOname(String oname) { this.oname = oname; System.out.println("第二步,调用set方法设置值"); } private String oname; //创建执行的初始化方法 public void initMethod(){ System.out.println("第三步,执行初始化方法"); } //创建执行销毁的方法 public void destroyMethod(){ System.out.println("第五步,执行销毁方法"); } }
package com.bean; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.lang.Nullable; public class MyBeanPost 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; } }
<?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"> <!--提取list集合类型属性注入使用--> <bean id="orders" class="com.bean.Orders" init-method="initMethod" destroy-method="destroyMethod"> <property name="oname" value="手机"></property> </bean> <!--配置后置处理器--> <bean id="myBeanPost" class="com.bean.MyBeanPost"></bean> </beans>