P命名空间注入
-
添加xmlns约束
xmlns:p="http://www.springframework.org/schema/p"
-
使用p命名空间进行属性注入
bean9.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" xmlns:p="http://www.springframework.org/schema/p" 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 "> <!-- p命名空间,要引入xmlns:p="http://www.springframework.org/schema/p" --> <!-- 引入bean8对象 --> <import resource="bean8.xml"/> <bean name="studentp" class="NewStudent" p:SName="李华" p:SNumber="114514" p:teacherMap-ref="teacherMap" p:lessons-ref="lessonList"> </bean></beans>
-
编写测试方法
@Test public void testPName() { //加载spring配置文件 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean9.xml"); //获取bean NewStudent Student = (NewStudent) applicationContext.getBean("studentp"); System.out.println(Student.toString()); }
-
输出
NewStudent(sName=李华, sNumber=114514, teacherMap={1=Teacher(tName=李老师, tNumber=20000), 2=Teacher(tName=刘老师, tNumber=20001), 3=Teacher(tName=张老师, tNumber=20002)}, lessons=[Lesson(LName=数学), Lesson(LName=语文), Lesson(LName=英语)])
引入外部属性文件
-
引入数据库相关依赖
<!--MySQL驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.30</version> </dependency> <!--数据源--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.31</version> </dependency>
-
创建外部属性文件properties,定义数据信息
jdbc.user=root jdbc.password=root jdbc.url=jdbc:mysql://localhost:3306/spring?serverTimezone=UTC jdbc.driver=com.mysql.cj.jdbc.Driver
-
创建spring配置文件,引入context命名空间,引入属性文件,使表达式完成注入
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--引入外部属性文件--> <context:property-placeholder location="classpath:jdbc.properties"/> <!--完成数据库信息注入--> <bean name="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.user}"/> <property name="password" value="${jdbc.password}"/> <property name="driverClassName" value="${jdbc.driver}"/> </bean></beans>
-
编写测试方法获取对象
@Test public void testJdbc(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean-jdbc.xml"); DruidDataSource druidDataSource=(DruidDataSource)applicationContext.getBean("druidDataSource"); System.out.println("Url:"+druidDataSource.getUrl()); System.out.println("Username:"+druidDataSource.getUsername()); System.out.println("Password:"+druidDataSource.getPassword()); System.out.println("DriverClassName:"+druidDataSource.getDriverClassName());
}
```
-
输出结果
Url:jdbc:mysql://localhost:3306/spring?serverTimezone=UTC Username:root Password:root DriverClassName:com.mysql.cj.jdbc.Driver
Bean的作用域
在Spring中可以通过配置bean标签的scope属性来指定bean的作用域范围
取值 | 作用 | 创建对象的时机 |
---|---|---|
singleton | 这个bean的对象在IOC容器中始终为单实例 | 1OC容器初始化时 |
prototype | 这个bean在IOC容器中有多个实例 | 获取bean时 |
在WebApplicationContext环境下还会有另外几个作用域(但不常用)
取值 | 作用 |
---|---|
request | 在一个请求中有效 |
session | 在一个会话中有效 |
-
创建一个Order类,为了在sout对象时能输出对象的地址,不要重写toString()
public class Order { }
-
注入单例对象和多例对象
11-bean-scope.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="order1" class="Order" scope="singleton"/> <!-- 创建多例对象 --> <bean id="order2" class="Order" scope="prototype"/> </beans>
-
编写测试方法
@Test public void testScope(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("11-bean-scope.xml"); Order Order1_1=(Order)applicationContext.getBean("order1"); Order Order1_2=(Order)applicationContext.getBean("order1"); System.out.println("单例对象输出:"); System.out.println("Order1_1:"+Order1_1); System.out.println("Order1_2:"+Order1_2); Order Order2_1=(Order)applicationContext.getBean("order2"); Order Order2_2=(Order)applicationContext.getBean("order2"); System.out.println("多例对象输出:"); System.out.println("lesson2_1:"+Order2_1); System.out.println("lesson2_2:"+Order2_2); }
-
输出结果
单例对象输出: Order1_1:Order@3738449f Order1_2:Order@3738449f 多例对象输出: lesson2_1:Order@69e1dd28 lesson2_2:Order@11bd0f3b
Bean生命周期
①具体的生命周期过程
- bean对象创建(调用无参构造器)
- 给bean对象设置属性
- bean的后置处理器(初始化之前)
- bean对象初始化(需在配置bean时指定初始化方法)
- bean的后置处理器(初始化之后)
- bean对象就绪可以使用
- bean对象销毁(需在配置bean时指定销毁方法)
- 1OC容器关闭
-
创建AnyClass类
import lombok.Getter; @Getter public class AnyClass { private String name; void AnyClass(){ System.out.println("Bean对象创建,调用无参构造"); } public void setName(String name) { this.name = name; System.out.println("Bean对象属性设置,调用setter"); } public void initMethods(){ System.out.println("调用指定的初始化方法"); } public void destroyMethods(){ System.out.println("调用指定的销毁方法"); } }
-
创建MyBeanPost类,重写BeanPostProcessor的后置配置器方法
import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBeanPost implements BeanPostProcessor { //初始化之前执行 @Override public Object postProcessBeforeInitialization(Object bean, String beanName) { System.out.println("Bean后置处理器,初始化之前执行"); return bean; } //初始化之后执行 @Override public Object postProcessAfterInitialization(Object bean, String beanName) { System.out.println("Bean后置处理器,初始化之后执行"); return bean; } }
-
注入AnyClass类和MyBeanPost类
<?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"> <!-- init-method:指定初始化方法 --> <!-- destroy-method:指定销毁方法 --> <bean id="anyCLass1" class="AnyClass" init-method="initMethods" destroy-method="destroyMethods"> <property name="name" value="ClassName"/> </bean> <!-- 后置处理器需要放入ioc才能生效 --> <bean id="myBeanPost" class="MyBeanPost"/> </beans>
-
编写测试方法
@Test public void testLifetime(){ //要调用销毁方法就不能使用ApplicationContext ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext("12-bean-lifetime.xml"); AnyClass anyClass=(AnyClass)classPathXmlApplicationContext.getBean("anyCLass1"); System.out.println("对象创建完成,可以使用:"+anyClass); System.out.println("对象开始销毁"); classPathXmlApplicationContext.close(); }
-
输出:
Bean对象属性设置,调用setter Bean后置处理器,初始化之前执行 调用指定的初始化方法 Bean后置处理器,初始化之后执行 对象创建完成,可以使用:AnyClass@505fc5a4 对象开始销毁 调用指定的销毁方法
FactoryBean
FactoryBean,是Spring提供的一种整合第三方框架的常用机制。和普通的bean不同,配置一个FactoryBean类型的bean,在获取bean的时候得到的并不是class,属性中配置的这个类的对象,而是getObject()方法的返回值。
通过这种机制,Sping可以帮我们把复杂组件创建的详细过程和繁琐细节都屏蔽起来,只展示最简洁的使用界面。
在整合mybatis时,Spring就是通过FactoryBean机制来帮我们创建SqlSessionFactory对象的。
-
创建AnyClass类(上文已有)
-
创建MyFactoryBean类,继承BeanPostProcessor的后置配置器方法,重写必要方法
import org.springframework.beans.factory.FactoryBean; public class MyFactoryBean implements FactoryBean<AnyClass> { @Override public AnyClass getObject() throws Exception { return new AnyClass(); } @Override public Class<?> getObjectType() { return AnyClass.class; } }
-
注入MyFactoryBean类
<?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="anyClass1" class="MyFactoryBean"/> </beans>
-
编写测试方法
@Test public void testFactoryBean(){ ApplicationContext applicationContext=new ClassPathXmlApplicationContext("13-bean-factorybean.xml"); AnyClass anyClass=(AnyClass) applicationContext.getBean("anyClass1"); System.out.println(anyClass); }
-
输出结果
AnyClass@41e1e210
基于xml自动装配
创建一组MVC架构套件
dao.UserDao.java
package dao;
public interface UserDao {
public void work();
}
dao.UserDaoImpl.java
package dao;
import lombok.Setter;
@Setter
public class UserDaoImpl implements UserDao{
@Override
public void work() {
System.out.println("UserDao-work");
}
}
service.UserService.java
package service;
public interface UserService {
public void Work();
}
service.UserServiceImpl.java
package service;
import dao.UserDao;
import lombok.Setter;
@Setter
public class UserServiceImpl implements UserService{
private UserDao userDao;
@Override
public void Work() {
System.out.println("UserService-work");
userDao.work();
}
}
controller.UserController.java
package controller;
import lombok.Setter;
import service.UserService;
@Setter
public class UserController {
private UserService userService;
public void work(){
System.out.println("UserController-work");
userService.Work();
}
}
注入属性
<?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="userService" class="service.UserServiceImpl" autowire="byType"/>
<bean id="userController" class="controller.UserController" autowire="byType"/>
<bean id="userDao" class="dao.UserDaoImpl" autowire="byType"/>
</beans>
编写测试方法
@Test
public void testAutoWire() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("auto-wire-bean.xml");
UserController userController=(UserController)applicationContext.getBean("userController",UserController.class);
userController.work();
}
输出结果
UserController-work
UserService-work
UserDao-work
byType:根据类型匹配IOC容器中的某个兼容类型的bean,为属性自动赋值
若在IOC中,没有任何个兼容类型的bean能够为属性赋值,则该属性不装配,即值为默认值null
若在IOC中,有多个兼容类型的bean能够为属性赋值,则抛出异常NoUniqueBeanDefinitionException