Java 阶段三 Day08 基于XML和注解管理Bean
基于XML管理bean
在Java中,“bean” 是指被Spring框架管理的Java对象。Spring容器负责创建、配置和管理这些bean,以便在应用程序中使用。
bean的作用域
Spring框架支持不同的作用域来定义bean的生命周期和可见性。以下是Spring中常见的bean作用域:
-
Singleton(单例)作用域:
- 这是默认的作用域。
- 在整个Spring容器中,只创建一个bean实例。
- 所有通过容器获取的对象都共享同一个bean实例。
-
Prototype(原型)作用域:
- 每次请求都会创建一个新的bean实例。
- 每次通过容器获取对象时,都会返回一个不同的bean实例。
-
Request(请求)作用域(仅适用于Web应用程序):
- 在每个HTTP请求中,都会创建一个新的bean实例。
- 每个HTTP请求都拥有独立的bean实例。
-
Session(会话)作用域(仅适用于Web应用程序):
- 在每个用户会话中,都会创建一个新的bean实例。
- 每个用户会话都拥有独立的bean实例。
-
GlobalSession(全局会话)作用域(仅适用于分布式Web应用程序):
- 在全局会话中,通常由Portlet容器管理,创建一个新的bean实例。
- 这个作用域通常用于多个Portlet之间共享信息。
-
Custom Scope(自定义作用域):
- 你可以自定义作用域,以满足特定的需求。
- 你需要实现
org.springframework.beans.factory.config.Scope
接口,并配置Spring容器以使用自定义作用域。
选择合适的作用域取决于你的应用程序需求。通常情况下,大多数bean都使用默认的单例作用域,因为它具有良好的性能,并且在大多数情况下足够。然而,在需要多个实例的情况下,如Web应用程序中的会话级别或请求级别bean,可以选择其他作用域。
常用的两种为singleton(默认)和 prototype:
取值 | 含义 | 创建对象时机 |
---|---|---|
singleton(默认) | 在IoC容器中,这个bean的对象为单实例 | IoC容器初始化时 |
prototype | 这个bean在IoC容器中有多个实例 | 获取bean,即getBean()时 |
在Spring中,可以通过配置 <bean>
标签的 scope
属性来指定一个 bean 的作用域范围。
-
Singleton (单例)
<bean id="mySingletonBean" class="com.example.MySingletonBean" scope="singleton"/>
-
Prototype (原型)
<bean id="myPrototypeBean" class="com.example.MyPrototypeBean" scope="prototype"/>
bean的生命周期
在Spring中,bean的生命周期包括以下阶段:
-
实例化(Instantiation):在这个阶段,Spring容器创建bean的实例,并为其分配空间。这通常涉及到使用Java的构造函数来实例化对象。在实例化之前,可以执行一些配置,例如依赖注入。
-
属性注入(Populate Properties):在实例化之后,Spring容器会将bean的属性(依赖)注入到bean实例中,这个过程可以通过set方法完成。通常包括基于XML配置文件或注解的依赖注入。
-
设置Bean名称(Set Bean Name):Spring容器会将bean的名称(ID或名称)分配给bean实例。
-
Bean初始化方法调用(Initialization):在bean实例化和属性注入之后,Spring容器调用bean的初始化方法(如果有定义的话)。这个初始化方法可以是自定义的方法,也可以是由Spring提供的标准初始化方法,例如
init-method
属性或@PostConstruct
注解。 -
Bean使用(In Use):此阶段表示bean处于活动状态,可以被应用程序使用。
-
Bean销毁方法调用(Destruction):在bean不再需要时,Spring容器会调用bean的销毁方法(如果有定义的话)。这个销毁方法可以是自定义的方法,也可以是由Spring提供的标准销毁方法,例如
destroy-method
属性或@PreDestroy
注解。 -
销毁(Disposal):在销毁方法调用之后,bean的实例会被销毁,并且占用的资源会被释放。
这些生命周期阶段允许您在bean的不同点上执行特定的操作。您可以通过配置XML文件、Java配置或使用注解来定义初始化方法和销毁方法。Spring容器负责管理bean的生命周期,确保在适当的时候调用初始化方法和销毁方法。
以下是一个典型的bean生命周期示例,假设有一个名为User
的bean:
User.java
@Component
public class User {
private String username;
// 构造函数
public User() {
System.out.println("User被实例化");
}
// 初始化方法
// @PostConstruct
public void init() {
System.out.println("User初始化方法被调用");
}
// 销毁方法
// @Predestroy
public void destroy() {
System.out.println("User销毁方法被调用");
}
public String getUsername() {
return username;
}
// @Value("root")
public void setUsername(String username) {
System.out.println("通过set方法给bean对象属性赋值");
this.username = username;
}
在XML配置中,您可以这样定义bean的生命周期:
bean-life.xml
<bean id="user" class="com.example.User" init-method="init" destroy-method="destroy">
<property name = "username" value = "左老三"/>
</bean>
在测试类中:
UserTest.java
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserTest {
@Test
public void test(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean-life.xml");
User user = context.getBean("user", User.class);
System.out.println("使用bean阶段");
System.out.println("user = " + user);
//销毁方法
context.close();
}
}
在这个示例中,init-method
属性指定了初始化方法的名称,destroy-method
属性指定了销毁方法的名称。Spring容器将在实例化、初始化、使用和销毁bean时自动调用这些方法。
后置处理器处理展示
在Spring中,后置处理器(Post Processor)是一种机制,它允许您在容器实例化和配置bean之后以及在销毁bean之前对bean进行自定义处理。后置处理器通常用于在bean生命周期的不同阶段执行额外的逻辑,例如修改bean的属性,执行安全检查,或者执行特定的初始化或清理操作。
在Spring中,有两个主要的后置处理器接口,它们是:
-
BeanPostProcessor:这是一个接口,它定义了两个方法
postProcessBeforeInitialization
和postProcessAfterInitialization
,允许您在bean的初始化之前和之后执行自定义处理逻辑。public interface BeanPostProcessor { Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }
可以实现这个接口并在Spring配置文件中注册自定义的BeanPostProcessor,以便在bean初始化前后执行自定义逻辑。
-
DestructionAwareBeanPostProcessor:这是一个扩展了BeanPostProcessor接口的子接口,它添加了一个用于销毁阶段的回调方法
postProcessBeforeDestruction
。public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor { void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException; }
使用DestructionAwareBeanPostProcessor,您可以在bean销毁之前执行自定义逻辑。
以下是一个示例,演示如何实现和配置BeanPostProcessor:
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class CustomBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // 在bean初始化前执行自定义逻辑 System.out.println("Before Initialization: Bean Name - " + beanName); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // 在bean初始化后执行自定义逻辑 System.out.println("After Initialization: Bean Name - " + beanName); return bean; } }
然后,在Spring配置文件中注册自定义的BeanPostProcessor:
<bean id="CustomBeanPostProcessor" class="com.example.CustomBeanPostProcessor" />
通过这样的配置,您的自定义后置处理器将会在每个bean的初始化前后执行,并且您可以在这些方法中执行您希望的自定义逻辑。同样,您也可以实现
DestructionAwareBeanPostProcessor
接口来处理bean的销毁阶段的逻辑。
基于XML的自动装配
在Spring框架中,基于XML的自动装配是一种通过XML配置文件来指定Spring容器如何自动装配(注入依赖)bean之间的依赖关系的方式。Spring提供了三种主要的自动装配模式:
-
no (默认值):不进行自动装配,您需要手动指定bean之间的依赖关系。这是默认的模式,需要使用
<property>
或<constructor-arg>
元素来手动配置依赖。 -
byName:按照属性或构造函数参数的名称自动装配bean。Spring容器会尝试查找与属性或参数名称相同的bean,并将其注入到目标bean中。要启用按名称自动装配,可以在bean的定义中使用
autowire="byName"
。<bean id="person" class="com.example.Person" autowire="byName">
在上面的示例中,如果
Person
类有一个名为address
的属性,Spring将尝试查找一个名为address
的bean,并将其自动注入到Person
中。 -
byType:按照属性或构造函数参数的数据类型自动装配bean。Spring容器会尝试查找与属性或参数类型匹配的bean,并将其注入到目标bean中。要启用按类型自动装配,可以在bean的定义中使用
autowire="byType"
。<bean id="person" class="com.example.Person" autowire="byType">
在上面的示例中,如果
Person
类有一个属性的类型是Address
,Spring将尝试查找一个类型为Address
的bean,并将其自动注入到Person
中。 -
constructor:按照构造函数参数的类型自动装配bean。这与
byType
类似,但是是通过构造函数参数来进行自动装配。要启用按构造函数自动装配,可以在bean的定义中使用autowire="constructor"
。<bean id="person" class="com.example.Person" autowire="constructor">
在上面的示例中,Spring将尝试查找与
Person
构造函数参数的类型匹配的bean,并将其自动注入到Person
的构造函数中。
以下是一个完整的XML配置示例,演示了如何使用基于XML的自动装配:
<bean id="address" class="com.example.Address" />
<bean id="person" class="com.example.Person" autowire="byName">
<!-- 使用byName自动装配,将会自动注入名为address的bean -->
</bean>
需要注意的是,基于XML的自动装配可以减少手动配置的工作,但需要注意确保bean的名称或类型与依赖的bean匹配,否则可能会导致自动装配失败。在复杂的应用程序中,建议使用基于注解的自动装配(如@Autowired
)或基于Java配置来更灵活地管理依赖关系。
注意:
- 如果在IoC中,没有任何一个兼容类型的bean能够为属性赋值,则该属性不装配,默认值为null
- 如果在IoC中,有多个兼容类型的bean能够为属性赋值,则抛出异常
NoUniqueBeanDefinitionException
基于注解管理bean
在Spring框架中,可以使用注解(Annotation)来管理bean,这种方式称为基于注解的bean管理。通过注解,您可以更轻松地配置和管理Spring应用程序中的bean依赖关系,而无需使用XML配置文件。以下是一些常用的基于注解的bean管理方式:
-
@Component及其派生注解:Spring提供了一系列用于标记组件的注解,最常见的是
@Component
。您可以使用这些注解来标记Java类,Spring容器将自动扫描这些类并将它们注册为bean。@Component public class MyComponent { // 类的实现 }
在配置类中,您需要启用组件扫描:
@Configuration @ComponentScan(basePackages = "com.example") public class AppConfig { // 配置类的内容 }
-
@Autowired:
@Autowired
注解用于自动注入依赖关系,可以用在字段、构造函数、或setter方法上。Spring容器将查找匹配依赖类型的bean并注入。@Component public class MyService { private MyRepository repository; @Autowired public MyService(MyRepository repository) { this.repository = repository; } }
注意:要使
@Autowired
注解生效,您需要在配置类中启用自动装配(@ComponentScan
)。 -
@Qualifier:
@Qualifier
注解可与@Autowired
一起使用,用于标识具体要注入的bean名称,解决多个匹配的依赖。@Component public class MyService { private MyRepository repository; @Autowired public MyService(@Qualifier("myRepositoryImpl") MyRepository repository) { this.repository = repository; } }
-
@Configuration和@Bean:使用
@Configuration
注解标记一个类为配置类,使用@Bean
注解定义bean,这种方式适用于将第三方库或非Spring托管的类纳入Spring容器中。@Configuration public class AppConfig { @Bean public MyService myService() { return new MyService(); } }
这些是常用的基于注解的bean管理方式。为了使基于注解的bean管理生效,需要在Spring配置类中启用相应的注解配置,通常使用@ComponentScan
注解。
开启组件扫描
要在Spring应用程序中开启组件扫描,以便Spring容器能够自动识别和注册被注解标记的组件(例如 @Component
、@Service
、@Repository
等),您需要执行以下步骤:
-
创建配置类(可选):首先,您可以创建一个Java配置类,以便配置Spring容器的相关设置。这是可选的,但通常用于配置其他Bean和数据源等。以下是一个示例:
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan(basePackages = "com.example") public class AppConfig { // 可以在这里定义其他Bean和配置 }
在上面的示例中,
@ComponentScan
注解用于启用组件扫描,并指定了要扫描的基本包路径(例如com.example
)。这意味着Spring容器将在此包及其子包中查找被注解标记的组件。 -
在XML配置中引入配置类(可选):如果您使用XML配置来配置Spring应用程序,您可以使用
<context:component-scan>
元素来引入配置类。以下是一个示例:<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:component-scan base-package="com.example" /> <!-- 定义其他Bean和配置 --> </beans>
在上面的示例中,
<context:component-scan>
元素用于启用组件扫描,并指定了要扫描的基本包路径。 -
标记组件:确保您的Java类(如服务类、存储库类等)使用适当的注解(例如
@Component
、@Service
、@Repository
等)进行标记,以便Spring容器能够识别它们。例如:import org.springframework.stereotype.Service; @Service public class MyService { // 类的实现 }
-
启动Spring容器:在应用程序的入口点(例如
main
方法中)启动Spring容器,以便它可以扫描和注册被标记的组件。以下是一个示例:import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MainApp { public static void main(String[] args) { // 使用配置类启动Spring容器 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // 获取和使用Bean MyService myService = context.getBean(MyService.class); myService.doSomething(); // 关闭Spring容器 context.close(); } }
在上面的示例中,
AnnotationConfigApplicationContext
用于启动Spring容器,并通过传递配置类的类对象来告诉容器在哪里进行组件扫描。
通过以上步骤,可以成功启用组件扫描,Spring容器将自动识别和注册被注解标记的组件,使它们可用于应用程序。
使用注解定义Bean
在Spring中,您可以使用注解来定义bean,使Spring容器能够自动检测和注册这些bean。以下是一些常用的注解用于定义bean的示例:
-
@Component:
@Component
注解用于将普通的Java类标记为Spring组件。当启用组件扫描时,Spring容器会自动检测这些类并将它们注册为bean。import org.springframework.stereotype.Component; @Component public class MyComponent { // 类的实现 }
-
@Service:
@Service
注解通常用于标记服务层(Service)的类,它是@Component
的特化版本。它可以让您更明确地指定bean的用途。import org.springframework.stereotype.Service; @Service public class MyService { // 类的实现 }
-
@Repository:
@Repository
注解通常用于标记数据访问层(Repository)的类,它也是@Component
的特化版本。它表示这个类是一个数据访问组件。import org.springframework.stereotype.Repository; @Repository public class MyRepository { // 类的实现 }
-
@Controller:
@Controller
注解通常用于标记控制器类,它是@Component
的特化版本,用于处理Web请求。import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class MyController { @GetMapping("/hello") public String sayHello() { return "Hello, World!"; } }
-
@Configuration 和 @Bean:您可以使用
@Configuration
注解标记一个类为配置类,然后使用@Bean
注解来定义bean方法。这些bean方法会在配置类中被调用,从而将其返回值注册为bean。import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AppConfig { @Bean public MyService myService() { return new MyService(); } }
请注意,要使这些注解生效,您需要确保在Spring应用程序的配置中启用了组件扫描(通常使用 @ComponentScan
注解或XML配置中的 <context:component-scan>
元素)。Spring容器将自动检测并注册使用这些注解标记的bean。
使用注解定义bean可以使您的代码更简洁、易于理解,并提高了代码的可维护性。这些注解是Spring框架中的一部分,不需要额外的配置。
属性值注入
@Autowired
注入
单独使用@Autowired
注解,默认根据类型装配(byType)
@Autowired
注解有一个required属性,默认值是true,表示在注入的时候要求被注入的Bean必须存在,如果不存在则报错。如果required属性设置为false,表示注入的Bean存在或者不存在都没关系,存在就注入,不存在也不报错。
@Autowired
注解用于自动注入bean的依赖关系。通过 @Autowired
注解,Spring容器会自动查找匹配的bean,并将其注入到目标bean中。以下是如何使用 @Autowired
注解进行依赖注入的示例:
-
依赖注入到字段:将依赖关系注入到类的字段上。
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class MyService { @Autowired private MyRepository repository; // 其他方法 }
-
依赖注入到构造函数:通过构造函数注入依赖关系。
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class MyService { private final MyRepository repository; @Autowired public MyService(MyRepository repository) { this.repository = repository; } // 其他方法 }
-
依赖注入到Setter方法:通过Setter方法注入依赖关系。
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class MyService { private MyRepository repository; @Autowired public void setRepository(MyRepository repository) { this.repository = repository; } // 其他方法 }
-
多个候选项时的 @Autowired 注解:如果有多个匹配的bean可供注入,可以使用
@Qualifier
注解指定要注入的bean的名称。import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component public class MyService { @Autowired @Qualifier("myRepositoryImpl") private MyRepository repository; // 其他方法 }
请注意,使用 @Autowired
进行注入需要在Spring应用程序的配置中启用自动装配(通常使用 @ComponentScan
注解或XML配置中的 <context:component-scan>
元素)。Spring容器会自动查找并注入匹配类型的bean。
如果您的项目中有多个bean类型与要注入的字段或构造函数参数类型匹配,您可以使用 @Qualifier
注解来指定具体要注入的bean名称,以避免歧义。
@Resource
注入
@Resource
是一种用于依赖注入的注解,它通常与Java EE(Java Platform, Enterprise Edition)一起使用,但在Spring中也可以使用。@Resource
注解默认根据名称装配byName
,未指定name时,使用属性名作为name,通过name找不到的话会自动启动通过类型byType
装配。而@Autowired
注解默认根据类型装配byType
,如果想根据名称匹配,需要配合@Qualifier
注解一起使用@Resource
注解用在属性上、setter方法上@Autowired
注解用在属性上、setter方法上、构造方法上、构造方法参数上
@Resource
注解两种常见的用法:
-
按照名称注入(byName):通过指定bean的名称来进行注入。
import javax.annotation.Resource; import org.springframework.stereotype.Component; @Component public class MyService { @Resource(name = "myRepositoryImpl") private MyRepository repository; // 其他方法 }
在上面的示例中,
@Resource(name = "myRepositoryImpl")
表示要按照名称 “myRepositoryImpl” 注入依赖关系。 -
按照类型注入(byType):通过指定bean的类型来进行注入。在这种情况下,
@Resource
会根据类型进行匹配。import javax.annotation.Resource; import org.springframework.stereotype.Component; @Component public class MyService { @Resource private MyRepository repository; // 其他方法 }
在上面的示例中,
@Resource
按照MyRepository
类型注入依赖关系。
需要注意的是,虽然 @Resource
注解在Spring中可以使用,但通常更推荐使用 @Autowired
注解,因为它提供更丰富的功能,并且是Spring的核心注解之一。使用 @Autowired
注解,您可以更灵活地处理依赖注入,包括按类型、按名称、按限定符等方式。但如果您的项目需要与Java EE兼容或使用Java EE容器(如Tomcat、JBoss等)时,@Resource
可能会更适合您的需求。
Spring全注解开发
Spring全注解开发是一种使用注解而不是XML配置文件来构建Spring应用程序的方法。在全注解开发中,您可以使用各种注解来定义bean、管理依赖关系以及配置应用程序。以下是实现Spring全注解开发的一般步骤:
-
创建Spring配置类:创建一个Java类,用于配置Spring应用程序。这个类通常使用
@Configuration
注解标记,以指示它是Spring的配置类。在配置类中,您可以定义bean、启用组件扫描等。import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ComponentScan; //声明此类为配置类 @Configuration //开启组件扫描 @ComponentScan(basePackages = "com.example.spring") public class AppConfig { // 配置相关内容 }
-
定义Bean:使用
@Component
或其他相关注解来定义bean。Spring容器会自动扫描并注册这些bean。import org.springframework.stereotype.Component; @Component public class MyComponent { // 类的实现 }
-
配置依赖注入:使用
@Autowired
、@Qualifier
和其他相关注解来配置依赖注入。Spring容器会自动解析和注入依赖关系。import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class MyService { private final MyRepository repository; @Autowired public MyService(MyRepository repository) { this.repository = repository; } }
@Qualifier
注解通常与@Autowired
注解一起使用,用于指定要注入的具体bean实现类,特别是在存在多个候选bean的情况下,以解决歧义问题。示例:假设有一个接口
MyRepository
和两个不同的实现类MyRepositoryImpl1
和MyRepositoryImpl2
。public interface MyRepository { // 方法声明 } @Component("myRepositoryImpl1") public class MyRepositoryImpl1 implements MyRepository { // 类的实现 } @Component("myRepositoryImpl2") public class MyRepositoryImpl2 implements MyRepository { // 类的实现 }
接着在
MyService
类中注入特定的MyRepository
实现类。使用@Autowired
注解结合@Qualifier
注解来指定实现类的名称:import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; @Service public class MyService { private final MyRepository myRepository; @Autowired @Qualifier("myRepositoryImpl1") // 指定要注入的实现类名称,在@Component注解中可以不用指定组件名称,默认为当前类的 类名首字母小写 public MyService(MyRepository myRepository) { this.myRepository = myRepository; } // 其他方法 }
在上面的示例中,
@Qualifier("myRepositoryImpl1")
指定了要注入的具体实现类的名称为 “myRepositoryImpl1”。 -
运行应用程序:创建Spring容器并加载配置类,然后从容器中获取bean并运行应用程序。
import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MainApp { public static void main(String[] args) { // 创建Spring容器并加载配置类 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // 获取bean并运行应用程序 MyService myService = context.getBean(MyService.class); myService.doSomething(); // 关闭Spring容器 context.close(); } }
-
运行应用程序:创建Spring容器并加载配置类,然后从容器中获取bean并运行应用程序。
import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MainApp { public static void main(String[] args) { // 创建Spring容器并加载配置类 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // 获取bean并运行应用程序 MyService myService = context.getBean(MyService.class); myService.doSomething(); // 关闭Spring容器 context.close(); } }
通过上述步骤,您可以实现Spring全注解开发,将应用程序的配置和组件管理全部放入Java代码和注解中,而无需XML配置文件。这种方式更加简洁、易于维护,特别适合小型和中小型项目。
面试题
描述一下bean的生命周期
- 第一步实例化,spring调用构造方法对bean实例化,分配出空间资源
- 第二步属性值的注入,调用setter方法对属性值进行注入
- 第三步初始化,可以调用指定的初始化方法进行前置操作,比如数据校验
- 第四步使用阶段,正常使用
- 第五步销毁,当应用程序停止时,Bean对象会销毁释放计算机资源,同时调用指定的销毁方法
- 后置处理器在对象初始化之前可拿到当前对象做一些操作处理,在初始化之后也可以做一些处理