赞
踩
IoC(控制反转)可以通过把类都交给IoC容器来做到充分解耦,调用对象可以从IoC容器中直接调用,在IoC容器里面初始化和创建的对象叫做Bean
在IoC中,不同的Bean可能会有继承关系,在IoC中也会对建立所需的依赖关系,这就是DI(依赖注入)
首先要在pom.xml导入spring的坐标
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.3</version>
</dependency>
</dependencies>
之后在文件夹resources中创建配置Bean的xml文件,如果你前面正确导入坐标这时候右键会出一个
xml configuration file - >spring config
<?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="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用<property>绑定
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
<?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 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的别名在<bean>中写name值就是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 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>
在<bean>中设置scope可以调节是单例还是多例 scope=“singleton”(默认),就是单例,创建多个其实用的都是一个类
**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>
标签是<property>,name是类里面的形参,ref是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>
<property>的顺序也可以改变
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; } }
标签是<constructor>其他和setter差不多
<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就行了
在<bean>中加入autowire="类型"就可以开启自动注入了(仅限引用),byType就是按类型去IoC容器里面找,但是如果你把一个类定义了多个Bean这里就会报错,不知道找哪一个
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一样,就把<list>改成<set>就可以了
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>100</value> <value>200</value> <value>300</value> </array> </property> <property name="list"> <list> <value>100</value> <value>200</value> <value>300</value> </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>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。