IoC(控制反转)可以通过把类都交给IoC容器来做到充分解耦,调用对象可以从IoC容器中直接调用,在IoC容器里面初始化和创建的对象叫做Bean
在IoC中,不同的Bean可能会有继承关系,在IoC中也会对建立所需的依赖关系,这就是DI(依赖注入)
首先要在pom.xml导入spring的坐标
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>6.1.3version>
dependency>
dependencies>
之后在文件夹resources中创建配置Bean的xml文件,如果你前面正确导入坐标这时候右键会出一个
xml configuration file - >spring config
<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="User" class="com.yuanshen.pojo.User">bean>
<bean id="Student" class="com.yuanshen.pojo.Student">bean>
beans>
之后创建两个类准备塞IoC容器里面
package com.yuanshen.pojo;
public class Student {
private User user = new User();
public void save(){
System.out.println("Student..");
user.save();
}
}
package com.yuanshen.pojo;
public class User {
public void save(){
System.out.println("User...");
}
}
之后在主函数里面创建IoC容器,然后调用获取Bean并运行方法
import com.yuanshen.pojo.Student;
import com.yuanshen.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
//获取IoC容器通过XML文件
ApplicationContext as = new ClassPathXmlApplicationContext("applicationContext.xml");
// User user = (User) as.getBean("User");
// user.save();
Student st = (Student) as.getBean("Student");
st.save();
}
}
上面在Student里还要new一个User,但是还可以通过DI实现Student和User的低耦合绑定
在xml文件中把Student和User用
public class Student {
private User user;
public void save() {
System.out.println("Student..");
user.save();
}
public void setUser(User user) {
this.user = user;
}
}
第一个name是 Student里的类名,第二个ref是赋予给user IoC容器中哪个Bean
<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 https://www.springframework.org/schema/util/spring-util.xsd">
<bean id="User" class="com.yuanshen.pojo.User">bean>
<bean id="Student" class="com.yuanshen.pojo.Student" >
<property name="user" ref="User"/>
bean>
beans>
Bean的别名在
<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 https://www.springframework.org/schema/util/spring-util.xsd">
<bean id="User" class="com.yuanshen.pojo.User" name="user,user2">bean>
<bean id="Student" class="com.yuanshen.pojo.Student" name="student student2" >
<property name="user" ref="User"/>
bean>
beans>
public class Main {
public static void main(String[] args) {
ApplicationContext as = new ClassPathXmlApplicationContext("applicationContext.xml");
Student st1 = (Student) as.getBean("student");
Student st2 = (Student) as.getBean("student");
System.out.println(st1);
System.out.println(st2);
}
}
像这样通过Bean创建两个类,这时候两个类打印出来的地址值是完全一样的
<bean id="Student" class="com.yuanshen.pojo.Student" name="student student2" scope="singleton">
<property name="user" ref="User"/>
bean>
在
**scope=“prototype”**是多例,这样每创建一个类都是开辟新的空间
类似于这种绑定类本身并直接构造调用都是空参构造,如果没有空参构造就会报错
public class Main {
public static void main(String[] args) {
ApplicationContext as = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) as.getBean("User");
}
}
public class User {
//设立一个空参构造
public User(){
System.out.println("construction~");
}
public void save(){
System.out.println("User...");
}
}
<bean id="User" class="com.yuanshen.pojo.User" name="user,user2">bean>
这样控制台就会输出一个 “construction~”
在创建bean的时候要写factory-method绑定构造函数就可以了
<bean class="Factory.UserStaticFactory" factory-method="createUser" id="createUser"/>
public class UserStaticFactory {
public static User createUser(){
return new User();
}
}
public class UserFactory {
public User createUser(){
return new User();
}
}
这种必须创建类才能调用的方法设置如下
<bean id="creatUser2" class="Factory.UserFactory"/>
<bean id="UserDo" factory-bean="creatUser2" factory-method="createUser"/>
Main函数
public class Main {
public static void main(String[] args) {
ApplicationContext as = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) as.getBean("UserDo");
}
}
但这种方法过于麻烦且臃肿,新建出来的bean有一个只是作为中间桥梁的作用,所以可以用FactoryBean
泛型是你要构造的类,isSingLetion是设置是否单例,true就是单例,false就是多例,默认就是单例
public class UserFactoryBean implements FactoryBean<User> {
@Override
public User getObject() throws Exception {
return new User();
}
@Override
public Class<?> getObjectType() {
return User.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
定义Bean的初始函数和销毁函数,在xml中设置init-method和destroy-method
public class User {
public User(){
System.out.println("construction~");
}
public void save(){
System.out.println("User...");
}
public void init(){
System.out.println("init...");
}
public void destroy(){
System.out.println("destroy...");
}
}
<bean id="User" class="com.yuanshen.pojo.User" name="user,user2"
init-method="init" destroy-method="destroy">
bean>
但是一定要在Main里面手动关闭IoC容器才能触发销毁函数,因为在进程结束后虚拟机会直接关闭,就不会触发销毁函数
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext as = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) as.getBean("User");
as.close();
}
}
或者加入关闭钩子
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext as = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) as.getBean("User");
as.registerShutdownHook();
}
}
初始化和销毁也可以用接口固定格式来写
public class User implements InitializingBean, DisposableBean {
public User(){
System.out.println("construction~");
}
public void save(){
System.out.println("User...");
}
@Override
public void destroy() throws Exception {
System.out.println("destroy...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("init");
}
}
xml文件就不懂绑定init-method和destroy-method了
<bean id="User" class="com.yuanshen.pojo.User" name="user,user2">bean>
标签是
<bean id="Student" class="com.yuanshen.pojo.Student" name="student student2" scope="prototype">
<property name="user1" ref="User"/>
<property name="user2" ref="User"/>
bean>
public class Student {
private User user1;
private User user2;
public void save() {
System.out.println("Student..");
user1.save();
}
public void setUser1(User user1) {
this.user1 = user1;
System.out.println("注入1");
}
public void setUser2(User user2) {
System.out.println("注入2");
this.user1 = user2;
}
}
如果是普通参数,那就把ref改成value
<bean id="Student" class="com.yuanshen.pojo.Student" name="student student2" scope="prototype">
<property name="age" value="18"/>
<property name="name" value="李四"/>
bean>
public class Student {
String name;
int age;
public void save() {
System.out.println("Student..");
}
public void setName(String name) {
System.out.println(name);
this.name = name;
}
public void setAge(int age) {
System.out.println(age);
this.age = age;
}
}
标签是
<bean id="Student" class="com.yuanshen.pojo.Student" name="student student2" scope="prototype">
<constructor-arg name="name" value="张三"/>
<constructor-arg name="age" value="18"/>
bean>
public class Student {
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
System.out.println(name + " " + age);
}
public void save() {
System.out.println("Student..");
}
}
引用类型也是把value改成ref就行了
在
ByName就是按名字去找,要求形参要和Bean的id名一致
<bean id="Student" class="com.yuanshen.pojo.Student" name="student student2" scope="prototype" autowire="byType">bean>
public class Student {
private User user;
public void setUser(User user) {
System.out.println(user);
this.user = user;
}
public void save() {
System.out.println("Student..");
}
}
如下图,set和list一样,就把改成
public class ListTest {
private int[] arr;
private List<String> list;
private Map<String,String> map;
private Properties properties;
public void setArr(int[] arr) {
this.arr = arr;
System.out.println(arr);
}
public void setList(List<String> list) {
this.list = list;
System.out.println(list);
}
public void setMap(Map<String, String> map) {
this.map = map;
System.out.println(map);
}
public void setProperties(Properties properties) {
this.properties = properties;
System.out.println(properties);
}
}
<bean id="listTest" class="com.yuanshen.pojo.ListTest">
<property name="arr">
<array>
<value>100value>
<value>200value>
<value>300value>
array>
property>
<property name="list">
<list>
<value>100value>
<value>200value>
<value>300value>
list>
property>
<property name="map">
<map>
<entry key="角色1" value="小可莉~"/>
<entry key="角色2" value="小刻晴~"/>
<entry key="角色3" value="小纳西妲~"/>
map>
property>
<property name="properties">
<props>
<prop key="角色1">小可莉~prop>
props>
property>
bean>