目录
前言:
BeanDefinition的家族系列
1、BeanDefintion的UML类图
2、BeanDefintion家族类详解
2.1、通用接口
2.2、BeanDefintion接口
2.3、AbstractBeanDefintion抽象类
2.4、GenericBeanDefinition类
2.5、 AnnotatedGenericBeanDefinition类
2.6、 ScannedGenericBeanDefinition类
2.7、RootBeanDefinition类
2.8、ChildBeanDefinition类
3、xml配置
3.1、BeanDefinition的常用属性
3.2、BeanDefinition的继承和注入
3.3、depends-on/init-method/destory-method
3.4、factory-bean/factory-method
3.5、look-up属性
3.6、replace-method属性
至此BeanDefintion家族相关类以及使用总结完毕。笔者才疏学浅,在本篇博文的分析中如果有理解不到的地方,欢迎大家批评指正。
前言:
笔者在一篇关于Spring的BeanFactory的分析的时候数次被BeanDefintion接口弄的云里雾里(有关笔者的Spring源码分析之一BeanFactory相关 感兴趣的可以看看),影响了自己对BeanFactory的阅读。这里趁这次机会好好的捋一捋有关BeanDefinition的家族系列。
一、BeanDefinition的家族系列
1、BeanDefintion的UML类图
话不多说直接上图,让我们一睹BeanDefinition的大家族。原谅笔者不才无法用一张UML类图概括完整个BeanDefinition家族
AnnotatedGenericBeanDefinition UML类图
ChildBeanDefinition UML类图
RootBeanDefinition UML类图
Spring容器启动的过程中,会将Bean解析成Spring内部的BeanDefinition结构。BeanDefintion是Spring提供的将我们使用xml或者注解修饰的需要spring管理的bean实例统一使用BeanDefintion抽象模式存放,并同时提供有关bean的其他属性信息(spring定义的),注入类型,是否懒加载 ,scope等等,从而便于spring管理和使用。
2、BeanDefintion家族类详解
2.1、通用接口
BeanDefintion实现类都会直接或者间接的继承如下接口:
- AttributeAccessor 接口提供相关属性attribute的设置和读取操作设置属性可以通过xml的<meta key="" value=""/>设置
- BeanMetadataElement接口获取一个包含元数据元素的配置源对象
- AttributeAccessorSupport抽象类 实现了AttributeAccessor接口 使用Map来提供属性的访问和操作
- BeanMetadataAttributeAccessor类 继承AttributeAccessorSupport 实现BeanMetadataElement 新增的功能是访问BeanMetadataAttribute类型的属性。
2.2、BeanDefintion接口
BeanDefintion是Beandefintion系列的顶层接口,继承AttributeAccessor接口和BeanMetadataElement接口 所以具备了访问bean属性 以及获取源对象的功能。 spring将我们需要托管的bean都转换为 BeanDefinition 该接口中包含如下属性setter getter接口方法:
parentName: 父beanDefinition 名
beanClassName: bean实例对象的class名字
scope: 单例或者原型
lazyInit: 是否懒加载
dependsOn: 该bean定义所有依赖的beanName 列表
autowireCandidate:是否为注入的候选者
autowire-candidate 属性设置为 false, 这样容器在查找自动装配对象时 将不考虑该 bean,
即它不会被考虑作为其他 bean 自动装配的候选者,
但是该 bean 本身还是可以使用自动装配来注入其他的 bean
primary:是否为唯一的注入候选者
factoryBeanName: 创建该bean的工厂BeanName
factoryMethodName:创建该bean的工厂MethodName
ConstructorArgumentValues:构造参数包装类
MutablePropertyValues:可变属性列表
scope:是否单例 是否原型
role: 用于标识Bean的分类 有三种标识1、用户定义的bean ROLE_APPLICATION 2、某些复杂的配置ROLE_SUPPORT 3、完全内部使用ROLE_INFRASTRUCTURE
description 获取描述
description:返回该bean定义来自的资源的描述(用于在出现错误时显示上下文)
originatingBeanDefinition:获取原始的bean定义
2.3、AbstractBeanDefintion抽象类
AbstractBeanDefintion抽象类完全的实现了BeanDefinition中定义的所有接口(提供了默认的实现方式),同时也提供了一些扩展字段qualifiers属性、MethodOverrides属性等。
// Bean 的Class 对象
private volatile Object beanClass;
// bean 的作用范围, 对应 bean 属性 scope (常见的就是单例/原型)
private String scope = SCOPE_DEFAULT;
// 是否是抽象, 来自 bean 属性的 abstract(抽象的类是不能直接生成对象)
private boolean abstractFlag = false;
// 是否延迟加载, 对应 bean 属性 lazy-init (值是否在使用 Bean的时候才正真的创建 Bean)
private boolean lazyInit = false;
// 自动注入模式, 对应 bean 属性 autowire (这个属性主要指 XML 描述的 beanDefinition, 在生成bean的对吼阶段, 获取容器中的对象, 自动装配在 BeanDefinition 对应的 Field 上)
private int autowireMode = AUTOWIRE_NO;
// 依赖检查, Spring 3.0 后 弃用这个属性
private int dependencyCheck = DEPENDENCY_CHECK_NONE;
// 用来表示一个 bean 的实例化依靠另一个 bean 先实例化(PS: 这个很少使用了)
private String[] dependsOn;
/**
* autowire-candidate 属性设置为 false,
* 这样容器在查找自动装配对象时
* 将不考虑该 bean, 即它不会被考虑作为其他 bean
* 自动装配的候选者, 但是该 bean
* 本身还是可以使用自动装配来注入其他的 bean
*/
private boolean autowireCandidate = true;
// 自动装配时当出现多个 bean 候选者时, 将作为首候选者 (PS: 使用比较少)
private boolean primary = false;
// 用于记录 Qualifier, 对应子元素 qualifier(当使用 @Autowired 时, 有多个候选Bean 时, 就通过这个Qualifier 来进行区分)
private final Map<String, AutowireCandidateQualifier> qualifiers =
new LinkedHashMap<String, AutowireCandidateQualifier>(0);
// 允许访问非公开的构造器和方法, 程序设置 (PS: 用得比较少)
private boolean nonPublicAccessAllowed = true;
/**
* 是否以一种宽松的模式解析构造函数, 默认 true
* 如果是 false, 则在如下情况
* interface ITest()
* class ITestImpl implement ITest();
* class Main {
* Main(ITest i) {}
* Main(ITestImpl i) {}
* }
* 抛出异常, 因为 Spring 无法准确确定哪个构造函数
* 程序设置
*
* lenient 宽大, 仁慈
*/
private boolean lenientConstructorResolution = true;
/**
* 对应 bean 属性 factory-bean 用法 (PS: 这里涉及 FactoryBean 这个概念, 这个类主要是解决: 创建一个类, 但创建这个类的过程比较长/条件比较多, 这时候就使用同一的抽象工厂模式(FactoryBean对象) 来创建对象)
* <bean id="instanceFactoryBean" class="example.chapter3.InstanceFactoryBean />
* <bean id="currentTime" factory-bean="instanceFactoryBean" factory-method="createTime" />
*/
private String factoryBeanName;
// 对应 bean 属性 factory-method
private String factoryMethodName;
// 记录构造函数注入属性, 对应 bean 属性 constructor-arg
private ConstructorArgumentValues constructorArgumentValues;
// 普通属性集合 (在XML 中定义Bean的信息时, 通常propertyValues里面有很多依赖信息)
private MutablePropertyValues propertyValues;
// 方法重写的持有者, 记录 lookup-method, replaced-method 元素(PS: 与此对应有注解Loopup, 但运用的比较少了)
private MethodOverrides methodOverrides = new MethodOverrides();
// 初始化方法, 对应 bean 属性 init-method (PS: 通过 实现InitializingBean 接口, 可以达到同样效果)
private String initMethodName;
// 销毁方法, 对应 bean 属性 destory-method (PS: 与之对应的是 DisposableBean, 一帮都是在这类方法中完成资源释放之类的操作)
private String destroyMethodName;
// 是否执行 init-method, 程序设置 (默认是 true)
private boolean enforceInitMethod = true;
// 是否执行 destory-method, 程序设置 (默认是 true)
private boolean enforceDestroyMethod = true;
// 是否是用户定义的而不是应用程序本身定义的, 创建 AOP 部分组件时为 true(见 ConfigBeanDefinitionbeanParser.parseAdvice 方法)
private boolean synthetic = false;
/**
* 定义这个 bean 的应用, APPLICATION: 用户, INFRASTRUCTURE(infrastructure 基础设施): 内部使用, 与用户无关, SUPPORT: 某些复杂配置的一部分程序设置, 一般都是 BeanDefinition.ROLE_APPLICATION;
*/
private int role = BeanDefinition.ROLE_APPLICATION;
// bean 的描述信息
private String description;
// 这个 bean 定义的资源 (其实就是 A.class 这个文件)
private Resource resource;
2.4、GenericBeanDefinition类
该类继承了AbstractBeanDefinition类,提供了一个设置父类BeanDefintion名字的属性,该类可以拥有自己的父类Beandefinition
2.5、 AnnotatedGenericBeanDefinition类
该类继承了GenericBeanDefinition类,将使用@Configuration 注解修饰的类包装成该类型的BeanDefinition对象。
//包含@Configuration 注释修改属性信息
private final AnnotationMetadata metadata;
//存储工厂方法的元数据
@Nullable
private MethodMetadata factoryMethodMetadata;
AnnotationGenericBeanDefinition在GenenricBeanDefinition的基础上提供了访问注解、工厂方法的机制
2.6、 ScannedGenericBeanDefinition类
该类继承了GenericBeanDefinition类,将使用@Component、@Service、@Controller等注解修饰的类包装成该类型的BeanDefinition对象。
//包含@Component、@Service、@Controller等注释修改属性信息
private final AnnotationMetadata metadata;
2.7、RootBeanDefinition类
RootBeanDefinition可以单独作为一个BeanDefinition,也可以作为其他BeanDefinition的父类。但是他不能作为其他BeanDefinition的子类(可以去看源码,在setParentName的时候,会抛出一个异常) RootBeanDefinition在AbstractBeanDefinition的基础上定义了更多属性,初始化Bean需要的信息基本完善。
2.8、ChildBeanDefinition类
ChildBeanDefinition相当于一个子类,不可以单独存在,必须要依赖一个父BeanDetintion。(最大的区别他的parentName属性是通过构造方法设置的,而且并没有提供一个无参构造方法给我们。)
3、xml配置
该小结主要使用具体的xml配置的实例,带我们直观的了解BeanDefinition接口中相关属性
3.1、BeanDefinition的常用属性
- spring-beans.xml的配置
<!--
id属性: bean实例的唯一标识
name属性: name可以存在多个以逗号或者分号分隔 如果存在id和name id为beanName name中会注册为其别名(多个)
如果没有id 从name中的第一个值逗号或者分号之前的值作为id 其余的作为别名
class属性:全限定类名
abstract属性:是否抽象
scope属性: 单例和原型
primary属性:声明该bean为自动装配的首选bean
lazy-init属性:是否懒加载 在使用该实例时候才进行初始化
bean的子属性
property 属性使用setter方法去设置bean实例的属性
name属性:属性名称 基本类型使用value属性赋值 引用类型使用ref属性赋值
constructor-arg 属性使用构造方法去设置bean实例的属性
index属性: 指定构造器参数的顺序以0开始
name属性: 属性名称
type属性: 指定属性class类型
基本类型使用value属性赋值 引用类型使用ref属性赋值
qualifier属性: 暂时不清楚
meta属性: BeanDefintion的Attribute属性,当需要里面的属性时,
可以通过BeanDefinition的getAttribute(key);方法获取,
description属性: BeanDefinition的描述信息 要放在开头
-->
<bean id="student" name="student" class="com.xiu.Student" abstract="false"
lazy-init="true" primary="true" scope="singleton" >
<!-- 定义bean实例的描述信息 -->
<description>这个是一个bean实例的描述</description>
<!-- 构造器形式的参数赋值 两种形式
一种使用index索引指定构造器参数的顺序 以0开始同时对应的类也需要有与此构造器参数顺序相关的构造方法 否则会出现提示错误
另一种 是使用name 显式的指定属性名(这种比较稳妥)
-->
<!-- <constructor-arg index="1" value="谢"></constructor-arg>-->
<!-- <constructor-arg index="0" value="18"></constructor-arg>-->
<constructor-arg name="name" value="谢"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<!-- 使用setter getter方法设置实例化的方式 -->
<property name="name" value="谢"/>
<property name="age" value="18"/>
<!-- 设置相关的attributes属性 key属性key值 value属性值-->
<meta key="key" value="values" />
<!--<qualifier />-->
<!--<lookup-method/>-->
<!--<replaced-method/>-->
</bean>
- 测试类
@Test
public void testBeanDefintion(){
XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-beans.xml"));
Student student = beanFactory.getBean("student", Student.class);
System.out.println("姓名:"+student.getName()+", 年龄:"+student.getAge());
//获取bean定义信息
BeanDefinition studentBeanDefinition = beanFactory.getBeanDefinition("student");
//1、获取构造器包装类(前提是使用构造器的形式进行实例化bean)
ConstructorArgumentValues constructorArgumentValues = studentBeanDefinition.getConstructorArgumentValues();
List<ConstructorArgumentValues.ValueHolder> genericArgumentValues = constructorArgumentValues.getGenericArgumentValues();
//获取构造器参数
System.out.print("获取构造器参数信息");
genericArgumentValues.stream().forEach(item -> {
System.out.println("name="+item.getName()+", type="+item.getType()+",value="+item.getValue());
});
//2、获取bean定义的属性信息(前提是使用属性property的形式进行实例化bean)
System.out.print("获取属性信息");
MutablePropertyValues propertyValues = studentBeanDefinition.getPropertyValues();
propertyValues.getPropertyValueList().stream().forEach(item->{
System.out.println("name="+item.getName()+",value="+item.getValue());
});
//获取bean实例是否抽象
System.out.println("是否抽象:"+studentBeanDefinition.isAbstract());
//是否主要候选者
System.out.println("是否懒加载:"+studentBeanDefinition.isLazyInit());
System.out.println("是否为注入的唯一候选bean:"+studentBeanDefinition.isPrimary());
String scope = studentBeanDefinition.getScope();
System.out.println("获取scope范围:"+scope);
//获取xml的meta 属性值
String value = (String) studentBeanDefinition.getAttribute("key");
System.out.println("获取attribute属性信息:"+value);
//获取秒速描述
String description = studentBeanDefinition.getDescription();
System.out.println(description);
}
- 测试结果
如上信息都好理解 除了primary属性 我们再下文有关注入功能描述的时候再讲解。
3.2、BeanDefinition的继承和注入
- spring bean的xml parent属性 和autowire属性 autowire-candidate属性
<!--
parent属性: 设置其父bean实例标识 使用该标识的bean 表明其是一个继承关系
autowire属性: 如果该bean实例有需要依赖的其他属性bean实例 autowire的意思就是spring帮你匹配容器里的bean,
而匹配规则有如下几种
no:不匹配,但是bean必须定义ref元素
byName:根据名字匹配(如果容器里没有该name的bean,则该属性为null)
byType:根据类型匹配(如果同时找多个相同类型的bean,则报错)
constructor:根据构造器匹配
default:如果在bean上指定了default,则它会去beans标签上去找default-autowire属性
-->
<bean id="parent" class="com.xiu.autoeire.Parent">
<property name="wealth" value="100000000"/>
</bean>
<!--autowire-candidate属性:false 设置哪些对象不参与自动注入
如果有两个类型一样的实例 比如如下的两个bean实例Wife和Daugther 均实现了Woman接口
下面的son需要使用Woman引用 默认使用按照类型注入 正常来说 程序会因为不知道如何注入哪一个
Woman接口实现类出现错误 这时如果在Wife或者Daugther 任何一个实例将其属性设置为false 则该对象
不会参与自动注入 则程序注入的时候只匹配到一个类型的bean实例 所以会正常使用
则被注入的时候 会出现无法确定注入哪个对象 如果给其他的类型设置autowire-candidate 为false
则该实例不会被选择注入-->
<bean id="wife" class="com.xiu.autoeire.Wife" autowire-candidate="false">
</bean>
<!--注意这里的id lover 和我对应的Son对象中的名字lover保持一致 为了验证ByName -->
<bean id="lover" class="com.xiu.autoeire.Daughter">
</bean>
<!--如果只要spring中一个类型只有一个bean 则可以使用autowire的byType spring会按照类型给
该bean实例按照class类型注入唯一的WoMan类型 -->
<bean id="son" class="com.xiu.autoeire.Son" parent="parent" >
<property name="life" value="泡妞"/>
</bean>
- 测试类
//父类
public class Parent {
//财富
private Double wealth;
//省略构造器和setter getter方法
}
public class Son extends Parent {
private String life;
//该属性用来验证autowire模式
private Woman lover;
//省略构造器和setter getter方法
}
//接口类
public interface Woman {
public void love();
}
public class Wife implements Woman {
@Override
public void love() {
System.out.println("我是妻子");
}
}
public class Daughter implements Woman {
@Override
public void love() {
System.out.println("我是我爸的上辈子的情人");
}
}
@Test
public void testAutoWire(){
XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-beans.xml"));
Son son = beanFactory.getBean("son", Son.class);
//Son继承了Parent的 该实例通过在son的实例配置xml 中使用parent属性 则son自动继承了父类的Wealth
System.out.println("我是富二代,我有"+son.getWealth()+"钱,我要去"+son.getLife());
//自动注入 通过类型 通过名字 等
son.action();
}
- 测试结果
3.3、depends-on/init-method/destory-method
spring bean的xml配置
<!--
depends-on属性:depends-on是指相对于ref强关联关系 关联关系不强的两者属性依赖使用的depends-on
比如系统需要启动多个服务 用户服务,订单服务等 只有多个服务启动成功后,才启动系统 这个产品可以使用该属性.
同时指定Bean初始化及销毁时的顺序,使用depends-on属性指定的Bean要先初始化完毕后才初始化当前Bean,
由于只有"singleton"Bean才能被Spring管理销毁,所以当指定的Bean都是"singleton"时,
使用depends-on属性指定的Bean要在指定的Bean之后销毁。衍生出如下的实例初始化init-method属性 和销毁调用 destroy-method属性
init-method属性: 初始化之前调用该init-method方法
destroy-method属性: bean实例被销毁后调用该destroy-method方法
-->
<!-- 用户服务 -->
<bean id="userService" class="com.xiu.service.dependson.UserService"
init-method="initMethod" destroy-method="destoryMethod"/>
<!-- 订单服务 -->
<bean id="orderService" class="com.xiu.service.dependson.OrderService"
init-method="initMethod" destroy-method="destoryMethod" />
<!-- 系统服务 -->
<bean id="system" class="com.xiu.service.dependson.MySystem"
depends-on="orderService,userService" init-method="initMethod"
destroy-method="destoryMethod"/>
- bean实例配置
用户服务类
//用户服务
public class UserService {
public void initMethod(){
System.out.println("用户服务实例化的初始化方法调用");
}
public void destoryMethod(){
System.out.println("用户服务实例化的销毁方法调用");
}
public UserService(){
System.out.println("用户服务启动完成");
}
}
订单服务类
//订单服务
public class OrderService {
public void initMethod(){
System.out.println("订单服务实例化的初始化方法调用");
}
public void destoryMethod(){
System.out.println("订单服务实例化的销毁方法调用");
}
public OrderService(){
System.out.println("订单服务启动完成");
}
}
系统类
//系统类
public class MySystem {
public void initMethod(){
System.out.println("系统实例化的初始化方法调用");
}
public void destoryMethod(){
System.out.println("系统实例化的销毁方法调用");
}
public MySystem(){
System.out.println("系统启动完成");
}
}
测试类
@Test
public void testDependOnAndInitDestory(){
XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-beans.xml"));
//获取系统
MySystem system = beanFactory.getBean("system", MySystem.class);
//销毁某个服务 则对应依赖该服务的系统也会被销毁
beanFactory.destroySingleton("userService");
}
- 输出结果:
总结:在三个服务类中都设置了init-method 和destory-method 两个方式 实例创建的时候会调用对应的init-method对应的方法,同时代码中销毁用户服务 其destory-method对应的方法会被调用。
再来说一下 depends-on属性,除了上面的场景下(依赖关系上面的xml配置已经讲述清除)之外。这里说一下depends-on依赖关系下 依赖方与被依赖方初始化和销毁顺序,从打印的日志可以清楚的知道MySystem 依赖UserService和OrderService,则获取MySystem时候先回初始化其depends-on依赖的UserService和OrderService(先执行两者的init-method对应的方法)
销毁的时候 如果销毁MySystem depends-on依赖的UserService和OrderService任何一个则需要先销毁MySystem实例。
3.4、factory-bean/factory-method
- spring 的bean xml配置
<!--
factory-bean/factory-method属性: 使用工厂方法注入bean 创建实例的bean 如果方法是静态方法 只需要使用factory-method属性
如果创建bean实例的的方法是工厂对象的非静态方法 则需要使用factory-bean 指明工厂bean实例 同时使用factory-method指明创建bean实例的方法名
-->
<!--实例化工厂对象-->
<!-- 使用非静态工厂方法获取对象 需要先实例化工厂对象 -->
<bean id="productFactory" class="com.xiu.service.factory.ProductFactory" />
<bean id="product"
factory-bean="productFactory" factory-method="createProduct"/>
<!-- 使用静态工厂方法获取对象 -->
<bean id="productStatic" class="com.xiu.service.factory.ProductFactory"
factory-method="createProductStatic"/>
- java类
public class Product {
public Product(){
System.out.println("创建产品成功");
}
}
//工厂类
public class ProductFactory {
//静态方法创建产品
public static Product createProductStatic(){
final Product product = new Product();
return product;
}
//非静态方法创建产品
public Product createProduct(){
final Product product = new Product();
return product;
}
}
测试类
@Test
public void testProductByFactory(){
XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-beans.xml"));
//通过静态工厂方法获取产品
Product productStatic = beanFactory.getBean("productStatic", Product.class);
//通过非静态工厂方法获取产品
Product product = beanFactory.getBean("product", Product.class);
}
- 输出结果
3.5、look-up属性
- spring bean xml配置
<!--
lookup-method属性: 假设一个单例模式的bean A需要引用另外一个非单例模式的bean B,为了在我们每次引用的时候都能拿到最新的bean B
所以Spring为我们提供了方法注入的方式来实现以上的场景。方法注入方式主要是通过<lookup-method/>标签
-->
<!-- 原型香蕉实例 -->
<bean id="banner" class="com.xiu.service.lookup.BannerFruit" scope="prototype" />
<!-- 原型苹果实例 -->
<bean id="apple" class="com.xiu.service.lookup.AppleFruit" scope="prototype" />
<!--getFreshFruit是一个抽象方法 具体的实现通过CGLIB 动态代理自动生成代理方法 同时将最新的水果实例返回
这样才能获取到“新鲜”水果-->
<bean id="fruitTray" class="com.xiu.service.lookup.FruitTray">
<lookup-method name="getFreshFruit" bean="banner"/>
</bean>
- java类配置
//水果接口
public interface Fruit {
public void getFruit();
}
//苹果水果类
public class AppleFruit implements Fruit {
@Override
public void getFruit() {
System.out.println("获取到新鲜的苹果");
}
}
//香蕉水果
public class BannerFruit implements Fruit {
@Override
public void getFruit() {
System.out.println("获取到新鲜的香蕉");
}
}
//果盘
public abstract class FruitTray {
//获取新鲜的水果 抽象方法
public abstract Fruit getFreshFruit();
}
测试类
@Test
public void testLookUp(){
XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-beans.xml"));
FruitTray fruitTray = beanFactory.getBean("fruitTray", FruitTray.class);
Fruit freshFruit = fruitTray.getFreshFruit();
freshFruit.getFruit();
}
- 输出结果
3.6、replace-method属性
- spring bean xml配置
<!-- replaced-method属性: 使用场景:动态替换原有的业务逻辑 -->
<bean id="gangster" class="com.xiu.service.replace.Gangster" >
<replaced-method name="action" replacer="undercover" />
</bean>
<bean id="undercover" class="com.xiu.service.replace.Undercover" >
</bean>
- java类
//原始类
public class Gangster {
public void action() { System.out.println("原始方法!");
}
}
//动态改变功能的类 需要实现MethodReplacer 接口中的reimplement方法
public class Undercover implements MethodReplacer {
public void action(){
System.out.println("方法已经被替换");
}
//该方法类似于动态代理
@Override
public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
action();
return null;
}
}
测试类
@Test
public void testReplaced(){
XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-beans.xml"));
Gangster gangster = beanFactory.getBean("gangster", Gangster.class);
gangster.action();
}
- 输出结果
至此BeanDefintion家族相关类以及使用总结完毕。笔者才疏学浅,在本篇博文的分析中如果有理解不到的地方,欢迎大家批评指正。
更多推荐
spring源码分析之BeanDefinition相关
发布评论