原则
开闭原则(OCP)
扩展新功能时,旧功能不需要更改。
依赖倒置原则(DIP)
上面依赖下面,上面一改动,下面程序会受到牵连。
面向接口、抽象编程,不要面向具体编程。(不喜欢 new)
降低程序耦合度,提升扩展力。
解决措施
1、控制反转 IoC
反转:
(1)不采用硬编程来 new 对象
(2)不采用硬编程来维护对象之间的关系
实现方式:
(1)依赖注入 DI
set 注入(set 函数赋值)
构造方法注入(构造函数赋值)
2、Spring 框架
spring 程序
构造
采取 maven 模式构造
在 pom.xml 导入相关配置
写入 Beans.xml 相关配置
Beans.xml 中配置 id 是唯一的
spring 实例化对象本质
调用本地无参构造函数
创建好的对象以键(id)值(bean 对象)对方式存入 map 中
导入 Beans.xml 文件需要写完整路径(根路径是 resource)
Beans.xml 文件可以导入自定义类也可以导入内置类
spring 底层的 IoC 实习
XML 解析 + 工厂模式 + 反射机制
工厂模式:将对象的创建和使用进行分离
解析配置文件的时候就创建了对象,不是在 getbean 才创建对象
启用 log4j2 日志框架
引入 log4j2 依赖
pom.xml
1 2 3 4 5 6 7 8 9 10 11 <!--log4j2的依赖--> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.19.0</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j2-impl</artifactId> <version>2.19.0</version> </dependency>
类的根路径下提供 log4j2.xml 配置文件
log4j2.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?xml version="1.0" encoding="UTF-8"?> <configuration> <loggers> <!-- level指定日志级别,从低到高的优先级: ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF --> <root level="DEBUG"> <appender-ref ref="spring6log"/> </root> </loggers> <appenders> <!--输出日志信息到控制台--> <console name="spring6log" target="SYSTEM_OUT"> <!--控制日志输出的格式--> <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss SSS} [%t] %-3level %logger{1024} - %msg%n"/> </console> </appenders> </configuration>
使用日志框架
1 2 Logger logger = LoggerFactory.getLogger(FirstSpringTest.class); logger.info("我是一条日志消息");
依赖注入
外部 Bean
bean 定义到外面,在 property 标签中使用 ref 属性进行注入。
1 2 3 <bean id="userServiceBean" class="com.powernode.spring6.service.UserService"> <property name="userDao" ref="userDaoBean"/> </bean>
内部 Bean
在 bean 标签中嵌套 bean 标签
1 2 3 4 5 <bean id="userServiceBean" class="com.powernode.spring6.service.UserService"> <property name="userDao"> <bean class="com.powernode.spring6.dao.UserDao"/> </property> </bean>
简单类型注入
简单类型包括:
● 基本数据类型
● 基本数据类型对应的包装类
● String 或其他的 CharSequence 子类
● Number 子类
● Date 子类
● Enum 子类
● URI
● URL
● Temporal 子类
● Locale
● Class
● 另外还包括以上简单值类型对应的数组类型
级联属性赋值
1 2 3 4 5 6 7 8 <bean id="student" class="com.powernode.spring6.beans.Student"> <property name="name" value="张三"/> <!--要点1:以下两行配置的顺序不能颠倒--> <property name="clazz" ref="clazzBean"/> <!--要点2:clazz属性必须有getter方法--> <property name="clazz.name" value="高三一班"/> </bean>
注入数组
1 2 3 4 5 6 7 8 9 <bean id="person" class="com.powernode.spring6.beans.Person"> <property name="favariteFoods"> <array> <value>鸡排</value> <value>汉堡</value> <value>鹅肝</value> </array> </property> </bean>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <bean id="goods1" class="com.powernode.spring6.beans.Goods"> <property name="name" value="西瓜"/> </bean> <bean id="goods2" class="com.powernode.spring6.beans.Goods"> <property name="name" value="苹果"/> </bean> <bean id="order" class="com.powernode.spring6.beans.Order"> <property name="goods"> <array> <!--这里使用ref标签即可--> <ref bean="goods1"/> <ref bean="goods2"/> </array> </property> </bean>
注入 List 集合
List 集合:有序可重复
People.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class People { // 一个人有多个名字 private List<String> names; public void setNames(List<String> names) { this.names = names; } @Override public String toString() { return "People{" + "names=" + names + '}'; } }
1 2 3 4 5 6 7 8 9 10 11 <bean id="peopleBean" class="com.powernode.spring6.beans.People"> <property name="names"> <list> <value>铁锤</value> <value>张三</value> <value>张三</value> <value>张三</value> <value>狼</value> </list> </property> </bean>
注入 Set 集合
Set 集合:无序不可重复
People.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class People { // 一个人有多个电话 private Set<String> phones; public void setPhones(Set<String> phones) { this.phones = phones; } //...... @Override public String toString() { return "People{" + "phones=" + phones + ", names=" + names + '}'; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 <bean id="peopleBean" class="com.powernode.spring6.beans.People"> <property name="phones"> <set> <!--非简单类型可以使用ref,简单类型使用value--> <value>110</value> <value>110</value> <value>120</value> <value>120</value> <value>119</value> <value>119</value> </set> </property> </bean>
注入 Map 集合
People.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class People { // 一个人有多个住址 private Map<Integer, String> addrs; public void setAddrs(Map<Integer, String> addrs) { this.addrs = addrs; } //...... @Override public String toString() { return "People{" + "addrs=" + addrs + ", phones=" + phones + ", names=" + names + '}'; } }
1 2 3 4 5 6 7 8 9 10 <bean id="peopleBean" class="com.powernode.spring6.beans.People"> <property name="addrs"> <map> <!--如果key不是简单类型,使用 key-ref 属性--> <!--如果value不是简单类型,使用 value-ref 属性--> <entry key="1" value="北京大兴区"/> <entry key="2" value="上海浦东区"/> <entry key="3" value="深圳宝安区"/> </map> </property>
注入 Properties
java.util.Properties 继承 java.util.Hashtable,所以 Properties 也是一个 Map 集合
People.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class People { private Properties properties; public void setProperties(Properties properties) { this.properties = properties; } //...... @Override public String toString() { return "People{" + "properties=" + properties + ", addrs=" + addrs + ", phones=" + phones + ", names=" + names + '}'; } }
1 2 3 4 5 6 7 8 9 10 <bean id="peopleBean" class="com.powernode.spring6.beans.People"> <property name="properties"> <props> <prop key="driver">com.mysql.cj.jdbc.Driver</prop> <prop key="url">jdbc:mysql://localhost:3306/spring</prop> <prop key="username">root</prop> <prop key="password">123456</prop> </props> </property> </bean>
注入 null 和空字符串
1 2 3 4 5 <bean id="vipBean" class="com.powernode.spring6.beans.Vip"> <property name="email"> <null/> </property> </bean>
1 2 3 4 5 6 7 8 <bean id="vipBean" class="com.powernode.spring6.beans.Vip"> <!--空串的第一种方式--> <!--<property name="email" value=""/>--> <!--空串的第二种方式--> <property name="email"> <value/> </property> </bean>
注入的值中含有特殊符号
XML 中有 5 个特殊字符,分别是:<、>、’、"、&
1 2 3 <bean id="mathBean" class="com.powernode.spring6.beans.Math"> <property name="result" value="2 < 3"/> </bean>
1 2 3 4 5 6 <bean id="mathBean" class="com.powernode.spring6.beans.Math"> <property name="result"> <!--只能使用value标签--> <value><![CDATA[2 < 3]]></value> </property> </bean>
p 命名空间注入
在 XML 头部信息中添加 p 命名空间的配置信息:xmlns:p=“http://www.springframework.org/schema/p ”
p 命名空间注入是基于 setter 方法的,所以需要对应的属性提供 setter 方法。
1 2 xmlns:p="http://www.springframework.org/schema/p" <bean id="customerBean" class="com.powernode.spring6.beans.Customer" p:name="zhangsan" p:age="20"/>
c 命名空间注入
需要在 xml 配置文件头部添加信息:xmlns:c=“http://www.springframework.org/schema/c ”
需要提供构造方法。
c 命名空间是依靠构造方法的。
1 2 xmlns:c="http://www.springframework.org/schema/c" <bean id="myTimeBean" class="com.powernode.spring6.beans.MyTime" c:_0="2008" c:_1="8" c:_2="8"/>
util 命名空间注入
配置多个数据源且引用相同时
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 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:properties id="prop"> <prop key="driver">com.mysql.cj.jdbc.Driver</prop> <prop key="url">jdbc:mysql://localhost:3306/spring</prop> <prop key="username">root</prop> <prop key="password">123456</prop> </util:properties> <bean id="dataSource1" class="com.powernode.spring6.beans.MyDataSource1"> <property name="properties" ref="prop"/> </bean> <bean id="dataSource2" class="com.powernode.spring6.beans.MyDataSource2"> <property name="properties" ref="prop"/> </bean>
基于 XML 的名称自动装配
UserService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 public class UserService { private UserDao aaa; // 这个set方法非常关键 public void setAaa(UserDao aaa) { this.aaa = aaa; } public void save(){ aaa.insert(); } }
1 2 3 <bean id="userService" class="com.powernode.spring6.service.UserService" autowire="byName"/> <bean id="aaa" class="com.powernode.spring6.dao.UserDao"/>
基于 XML 的类型自动装配
AccountService.java
1 2 3 4 5 6 7 8 9 10 11 public class AccountService { private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } public void save(){ accountDao.insert(); } }
1 2 3 4 <!--byType表示根据类型自动装配--> <bean id="accountService" class="com.powernode.spring6.service.AccountService" autowire="byType"/> <bean class="com.powernode.spring6.dao.AccountDao"/>
spring 引入外部属性配置文件
jdbc.properties
1 2 3 4 jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/spring jdbc.username=root jdbc.password=root123
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?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/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:property-placeholder location="jdbc.properties"/> <bean id="dataSource" class="com.powernode.spring6.beans.MyDataSource"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> </beans>
工厂模式
简单工厂模式
简单工厂模式的优点:
客户端程序不需要关心对象的创建细节,需要哪个对象时,只需要向工厂索要即可,初步实现了责任的分离。客户端只负责 “消费”,工厂负责 “生产”。生产和消费分离。
简单工厂模式的缺点:
缺点 1:工厂类集中了所有产品的创造逻辑,形成一个无所不知的全能类,有人把它叫做上帝类。显然工厂类非常关键,不能出问题,一旦出问题,整个系统瘫痪。
缺点 2:不符合 OCP 开闭原则,在进行系统扩展时,需要修改工厂类。
Spring 中的 BeanFactory 就使用了简单工厂模式。
简单工厂模式的角色包括三个:
抽象产品 角色
Weapon.java
1 2 3 4 5 6 public abstract class Weapon { /** * 所有的武器都有攻击行为 */ public abstract void attack(); }
具体产品 角色
Tank.java
1 2 3 4 5 6 public class Tank extends Weapon{ @Override public void attack() { System.out.println("坦克开炮!"); } }
Fighter.java
1 2 3 4 5 6 public class Fighter extends Weapon{ @Override public void attack() { System.out.println("战斗机投下原子弹!"); } }
Dagger.java
1 2 3 4 5 6 public class Dagger extends Weapon{ @Override public void attack() { System.out.println("砍他丫的!"); } }
工厂类 角色
WeaponFactory.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static Weapon get(String weaponType){ if (weaponType == null || weaponType.trim().length() == 0) { return null; } Weapon weapon = null; if ("TANK".equals(weaponType)) { weapon = new Tank(); } else if ("FIGHTER".equals(weaponType)) { weapon = new Fighter(); } else if ("DAGGER".equals(weaponType)) { weapon = new Dagger(); } else { throw new RuntimeException("不支持该武器!"); } return weapon; } }
主程序
1 2 3 4 5 6 7 8 9 10 11 12 public class Client { public static void main(String[] args) { Weapon weapon1 = WeaponFactory.get("TANK"); weapon1.attack(); Weapon weapon2 = WeaponFactory.get("FIGHTER"); weapon2.attack(); Weapon weapon3 = WeaponFactory.get("DAGGER"); weapon3.attack(); } }
工厂方法模式
工厂方法模式的角色包括:
抽象工厂角色
具体工厂角色
抽象产品角色
具体产品角色
如果想扩展一个新的产品,只要新增一个产品类,再新增一个该产品对应的工厂即可
工厂方法模式的优点:
一个调用者想创建一个对象,只要知道其名称就可以了。
扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
屏蔽产品的具体实现,调用者只关心产品的接口。
工厂方法模式的缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
抽象工厂模式
抽象工厂模式相对于工厂方法模式来说,就是工厂方法模式是针对一个产品系列的,而抽象工厂模式是针对多个产品系列的,即工厂方法模式是一个产品系列一个工厂类,而抽象工厂模式是多个产品系列一个工厂类。
抽象工厂中包含 4 个角色:
抽象工厂角色
具体工厂角色
抽象产品角色
具体产品角色
Bean 的实例化方式
通常包括 4 种方式
第一种:通过构造方法实例化
第二种:通过简单工厂模式实例化
第三种:通过 factory-bean 实例化
第四种:通过 FactoryBean 接口实例化
通过构造方法实例化
1 2 3 4 5 public class User { public User() { System.out.println("User类的无参数构造方法执行。"); } }
1 <bean id="userBean" class="com.powernode.spring6.bean.User"/>
1 2 3 4 5 public void testConstructor(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); User user = applicationContext.getBean("userBean", User.class); System.out.println(user); }
通过简单工厂模式实例化
1 2 3 4 5 public class VipFactory { public static Vip get(){ return new Vip(); } }
1 <bean id="vipBean" class="com.powernode.spring6.bean.VipFactory" factory-method="get"/>
1 2 3 4 5 public void testSimpleFactory(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); Vip vip = applicationContext.getBean("vipBean", Vip.class); System.out.println(vip); }
通过 factory-bean 实例化
通过工厂方法模式进行实例化。
1 2 3 4 5 public class OrderFactory { public Order get(){ return new Order(); } }
1 2 <bean id="orderFactory" class="com.powernode.spring6.bean.OrderFactory"/> <bean id="orderBean" factory-bean="orderFactory" factory-method="get"/>
1 2 3 4 5 public void testSelfFactoryBean(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); Order orderBean = applicationContext.getBean("orderBean", Order.class); System.out.println(orderBean); }
通过 FactoryBean 接口实例化
主要是对上一种方法的改进。
在 Spring 中,当你编写的类直接实现 FactoryBean 接口之后,factory-bean 不需要指定了,factory-method 也不需要指定了。
factory-bean 会自动指向实现 FactoryBean 接口的类,factory-method 会自动指向 getObject () 方法。
FactoryBean 在 Spring 中是一个接口。被称为 “工厂 Bean”。“工厂 Bean” 是一种特殊的 Bean。所有的 “工厂 Bean” 都是用来协助 Spring 框架来创建其他 Bean 对象的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class PersonFactoryBean implements FactoryBean<Person> { @Override public Person getObject() throws Exception { return new Person(); } @Override public Class<?> getObjectType() { return null; } @Override public boolean isSingleton() { // true表示单例 // false表示原型 return true; } }
1 <bean id="personBean" class="com.powernode.spring6.bean.PersonFactoryBean"/>
1 2 3 4 5 6 7 8 public void testFactoryBean(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); Person personBean = applicationContext.getBean("personBean", Person.class); System.out.println(personBean); Person personBean2 = applicationContext.getBean("personBean", Person.class); System.out.println(personBean2); }
注入自定义 Date
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class DateFactoryBean implements FactoryBean<Date> { // 定义属性接收日期字符串 private String date; // 通过构造方法给日期字符串属性赋值 public DateFactoryBean(String date) { this.date = date; } @Override public Date getObject() throws Exception { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); return sdf.parse(this.date); } @Override public Class<?> getObjectType() { return null; } }
1 2 3 4 5 6 7 <bean id="dateBean" class="com.powernode.spring6.bean.DateFactoryBean"> <constructor-arg name="date" value="1999-10-11"/> </bean> <bean id="studentBean" class="com.powernode.spring6.bean.Student"> <property name="birth" ref="dateBean"/> </bean>
1 2 3 4 5 public void testDate(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); Student studentBean = applicationContext.getBean("studentBean", Student.class); System.out.println(studentBean); }
Bean 的生命周期
5 步
步骤
第一步:实例化 Bean
第二步:Bean 属性赋值
第三步:初始化 Bean
第四步:使用 Bean
第五步:销毁 Bean
举例
第一:只有正常关闭 spring 容器,bean 的销毁方法才会被调用。
第二:ClassPathXmlApplicationContext 类才有 close () 方法。
第三:配置文件中的 init-method 指定初始化方法。destroy-method 指定销毁方法。
User.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class User { private String name; public User() { System.out.println("1.实例化Bean"); } public void setName(String name) { this.name = name; System.out.println("2.Bean属性赋值"); } public void initBean(){ System.out.println("3.初始化Bean"); } public void destroyBean(){ System.out.println("5.销毁Bean"); } }
1 2 3 <bean id="userBean" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean"> <property name="name" value="zhangsan"/> </bean>
1 2 3 4 5 6 7 8 public void testLifecycle(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); User userBean = applicationContext.getBean("userBean", User.class); System.out.println("4.使用Bean"); // 只有正常关闭spring容器才会执行销毁方法 ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext; context.close(); }
7 步
如果你还想在初始化前和初始化后添加代码,可以加入 “Bean 后处理器”。
步骤
1 2 3 4 5 6 7 8 9 10 11 12 13 public class LogBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("Bean后处理器的before方法执行,即将开始初始化"); return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName); } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("Bean后处理器的after方法执行,已完成初始化"); return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); } }
1 2 <!--配置Bean后处理器。这个后处理器将作用于当前配置文件中所有的bean。--> <bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/>
1 2 3 4 5 6 7 8 public void testLifecycle(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); User userBean = applicationContext.getBean("userBean", User.class); System.out.println("4.使用Bean"); // 只有正常关闭spring容器才会执行销毁方法 ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext; context.close(); }
10 步
步骤
第一步:实例化 Bean
第二步:Bean 属性赋值
第三步:检测 Bean 是否实现了 Aware 的相关接口,并设置相关依赖
第四步:Bean 后处理器 before 执行
第五步:检测 Bean 是否实现了 InitialzingBean 接口,并调用接口方法
第六步:初始化 Bean
第七步:Bean 后处理器 after 执行
第八步:使用 Bean
第九步:检测 Bean 是否实现了 DisposableBean 接口,并调用接口方法
第十步:销毁 Bean
Aware 的相关接口
Aware 相关的接口包括:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
当 Bean 实现了 BeanNameAware,Spring 会将 Bean 的名字传递给 Bean。
当 Bean 实现了 BeanClassLoaderAware,Spring 会将加载该 Bean 的类加载器传递给 Bean。
当 Bean 实现了 BeanFactoryAware,Spring 会将 Bean 工厂对象传递给 Bean。
试以上 10 步,可以让 User 类实现 5 个接口,并实现所有方法:
BeanNameAware
BeanClassLoaderAware
BeanFactoryAware
InitializingBean
DisposableBean
举例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public class User implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean { private String name; public User() { System.out.println("1.实例化Bean"); } public void setName(String name) { this.name = name; System.out.println("2.Bean属性赋值"); } public void initBean(){ System.out.println("6.初始化Bean"); } public void destroyBean(){ System.out.println("10.销毁Bean"); } @Override public void setBeanClassLoader(ClassLoader classLoader) { System.out.println("3.类加载器:" + classLoader); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("3.Bean工厂:" + beanFactory); } @Override public void setBeanName(String name) { System.out.println("3.bean名字:" + name); } @Override public void destroy() throws Exception { System.out.println("9.DisposableBean destroy"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("5.afterPropertiesSet执行"); } }
LogBeanPostProcessor.java
1 2 3 4 5 6 7 8 9 10 11 12 13 public class LogBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("4.Bean后处理器的before方法执行,即将开始初始化"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("7.Bean后处理器的after方法执行,已完成初始化"); return bean; } }
1 2 <!--配置Bean后处理器。这个后处理器将作用于当前配置文件中所有的bean。--> <bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/>
1 2 3 4 5 6 7 8 public void testLifecycle(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); User userBean = applicationContext.getBean("userBean", User.class); System.out.println("4.使用Bean"); // 只有正常关闭spring容器才会执行销毁方法 ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext; context.close(); }
自己 new 的对象让 Spring 管理
1 2 3 4 5 6 7 8 9 10 11 12 13 public void testBeanRegister(){ // 自己new的对象 User user = new User(); System.out.println(user); // 创建 默认可列表BeanFactory 对象 DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); // 注册Bean factory.registerSingleton("userBean", user); // 从spring容器中获取bean User userBean = factory.getBean("userBean", User.class); System.out.println(userBean); }
Bean 循环依赖