文章目录
一、背景
下面的代码,无论是IOC,DI,都需要创建BeanDefinition ,设置构造器、初始方法、销毁方法等,注册BeanDefinition到BeanFactory,写代码和调用还是很繁琐,很多重复代码,所以还需要进一步优化处理
public static void testRegistBean() throws Exception {
BeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(ForlanA.class);
beanDefinition.setInitMethodName("init");
beanDefinition.setDestroyMethodName("destroy");
List<Object> constructorArgumentValues = new ArrayList<>();
constructorArgumentValues.add("程序员1");
constructorArgumentValues.add(new BeanReference("forlanAA"));
beanDefinition.setConstructorArgumentValues(constructorArgumentValues);
beanFactory.registerBeanDefinition("forlanA", beanDefinition);
beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(ForlanAA.class);
beanDefinition.setInitMethodName("init");
beanDefinition.setDestroyMethodName("destroy");
constructorArgumentValues = new ArrayList<>();
constructorArgumentValues.add("程序员2");
beanDefinition.setConstructorArgumentValues(constructorArgumentValues);
beanFactory.registerBeanDefinition("forlanAA", beanDefinition);
ForlanA forlanA = (ForlanA) beanFactory.getBean("forlanA");
forlanA.introduceAll();
}
public static void testRegistBeanByStaticFactoryMethod() throws Exception {
BeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(ForlanFactory.class);
beanDefinition.setFactoryMethodName("getForlanByStaticMethod");
List<Object> constructorArgumentValues = new ArrayList<>();
constructorArgumentValues.add("静态工厂方法");
constructorArgumentValues.add(15);
beanDefinition.setConstructorArgumentValues(constructorArgumentValues);
beanFactory.registerBeanDefinition("forlanByStaticMethod", beanDefinition);
Forlan forlan = (Forlan) beanFactory.getBean("forlanByStaticMethod");
forlan.introduce0();
}
public static void testRegistBeanByFactoryMethod() throws Exception {
BeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(ForlanFactory.class);
String factoryBeanName = "forlanFactory";
beanFactory.registerBeanDefinition(factoryBeanName, beanDefinition);
beanDefinition = new GenericBeanDefinition();
beanDefinition.setFactoryBeanName(factoryBeanName);
beanDefinition.setFactoryMethodName("getForlan");
List<Object> constructorArgumentValues = new ArrayList<>();
constructorArgumentValues.add("工厂bean方式");
constructorArgumentValues.add(20);
beanDefinition.setConstructorArgumentValues(constructorArgumentValues);
beanFactory.registerBeanDefinition("forlan", beanDefinition);
Forlan forlan = (Forlan) beanFactory.getBean("forlan");
forlan.introduce0();
}
public static void testRegistComplexBean() throws Exception {
BeanDefinition beanDefinition1 = new GenericBeanDefinition();
beanDefinition1.setBeanClass(Forlan.class);
beanDefinition1.setInitMethodName("init");
beanDefinition1.setDestroyMethodName("destroy");
List<Object> constructorArgumentValues = new ArrayList<>();
constructorArgumentValues.add("构造注入");
constructorArgumentValues.add(15);
beanDefinition1.setConstructorArgumentValues(constructorArgumentValues);
beanDefinition1.setPrimary(true);
beanFactory.registerBeanDefinition("forlan1", beanDefinition1);
BeanDefinition beanDefinition2 = new GenericBeanDefinition();
beanDefinition2.setBeanClass(Forlan.class);
beanDefinition2.setInitMethodName("init");
beanDefinition2.setDestroyMethodName("destroy");
List<PropertyValue> propertyValues = new ArrayList<>();
propertyValues.add(new PropertyValue("name", "属性依赖"));
propertyValues.add(new PropertyValue("age", 18));
beanDefinition2.setPropertyValues(propertyValues);
beanFactory.registerBeanDefinition("forlan2", beanDefinition2);
// 默认读取Primary=true的Bean
Forlan forlan = (Forlan) beanFactory.getBean(Forlan.class);
forlan.introduce0();
}
二、解决
1、基于xml配置
思路
定义XML规范
写代码解析XML,完成Bean定义的注册
<?xml version="1.0" encoding="UTF-8"?>
<bean id="forlanA" class="cn.forlan.aop.beans.sample.ForlanA" init-method="init" destroy-method="destroy">
<constructor-arg type="java.lang.String" value="程序员3"/>
<constructor-arg ref="forlanAA"/>
</bean>
<bean id="forlanAA" class="cn.forlan.aop.beans.sample.ForlanAA" init-method="init" destroy-method="destroy">
<constructor-arg type="java.lang.String" value="程序员4"/>
</bean>
创建一个xml解析器
public class XmlBeanDefinitionReader {
private BeanDefinitionRegistry registry;
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
this.registry = registry;
}
public void loadBeanDefinitions(String xmlFilePath) throws Exception {
Document document = parseToDocument(xmlFilePath);
new BeanDefinitionParserDelegate(registry).parseDocumentRegisterBeanDefinition(document);
}
private Document parseToDocument(String xmlFilePath) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File(xmlFilePath));
return document;
}
}
解析xml标签信息
// 这个类待完善
public class BeanDefinitionParserDelegate {
public static final String BEANS_NAMESPACE_URI = "http://www.springframework.org/schema/beans";
public static final String MULTI_VALUE_ATTRIBUTE_DELIMITERS = ",; ";
public static final String TRUE_VALUE = "true";
public static final String FALSE_VALUE = "false";
public static final String DEFAULT_VALUE = "default";
public static final String DESCRIPTION_ELEMENT = "description";
public static final String AUTOWIRE_NO_VALUE = "no";
public static final String AUTOWIRE_BY_NAME_VALUE = "byName";
public static final String AUTOWIRE_BY_TYPE_VALUE = "byType";
public static final String AUTOWIRE_CONSTRUCTOR_VALUE = "constructor";
public static final String AUTOWIRE_AUTODETECT_VALUE = "autodetect";
public static final String NAME_ATTRIBUTE = "name";
public static final String BEAN_ELEMENT = "bean";
public static final String META_ELEMENT = "meta";
public static final String ID_ATTRIBUTE = "id";
public static final String PARENT_ATTRIBUTE = "parent";
public static final String CLASS_ATTRIBUTE = "class";
public static final String ABSTRACT_ATTRIBUTE = "abstract";
public static final String SCOPE_ATTRIBUTE = "scope";
private static final String SINGLETON_ATTRIBUTE = "singleton";
public static final String LAZY_INIT_ATTRIBUTE = "lazy-init";
public static final String AUTOWIRE_ATTRIBUTE = "autowire";
public static final String AUTOWIRE_CANDIDATE_ATTRIBUTE = "autowire-candidate";
public static final String PRIMARY_ATTRIBUTE = "primary";
public static final String DEPENDS_ON_ATTRIBUTE = "depends-on";
public static final String INIT_METHOD_ATTRIBUTE = "init-method";
public static final String DESTROY_METHOD_ATTRIBUTE = "destroy-method";
public static final String FACTORY_METHOD_ATTRIBUTE = "factory-method";
public static final String FACTORY_BEAN_ATTRIBUTE = "factory-bean";
public static final String CONSTRUCTOR_ARG_ELEMENT = "constructor-arg";
public static final String INDEX_ATTRIBUTE = "index";
public static final String TYPE_ATTRIBUTE = "type";
public static final String VALUE_TYPE_ATTRIBUTE = "value-type";
public static final String KEY_TYPE_ATTRIBUTE = "key-type";
public static final String PROPERTY_ELEMENT = "property";
public static final String REF_ATTRIBUTE = "ref";
public static final String VALUE_ATTRIBUTE = "value";
public static final String LOOKUP_METHOD_ELEMENT = "lookup-method";
public static final String REPLACED_METHOD_ELEMENT = "replaced-method";
public static final String REPLACER_ATTRIBUTE = "replacer";
public static final String ARG_TYPE_ELEMENT = "arg-type";
public static final String ARG_TYPE_MATCH_ATTRIBUTE = "match";
public static final String REF_ELEMENT = "ref";
public static final String IDREF_ELEMENT = "idref";
public static final String BEAN_REF_ATTRIBUTE = "bean";
public static final String PARENT_REF_ATTRIBUTE = "parent";
public static final String VALUE_ELEMENT = "value";
public static final String NULL_ELEMENT = "null";
public static final String ARRAY_ELEMENT = "array";
public static final String LIST_ELEMENT = "list";
public static final String SET_ELEMENT = "set";
public static final String MAP_ELEMENT = "map";
public static final String ENTRY_ELEMENT = "entry";
public static final String KEY_ELEMENT = "key";
public static final String KEY_ATTRIBUTE = "key";
public static final String KEY_REF_ATTRIBUTE = "key-ref";
public static final String VALUE_REF_ATTRIBUTE = "value-ref";
public static final String PROPS_ELEMENT = "props";
public static final String PROP_ELEMENT = "prop";
public static final String MERGE_ATTRIBUTE = "merge";
public static final String QUALIFIER_ELEMENT = "qualifier";
public static final String QUALIFIER_ATTRIBUTE_ELEMENT = "attribute";
public static final String DEFAULT_LAZY_INIT_ATTRIBUTE = "default-lazy-init";
public static final String DEFAULT_MERGE_ATTRIBUTE = "default-merge";
public static final String DEFAULT_AUTOWIRE_ATTRIBUTE = "default-autowire";
public static final String DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE = "default-autowire-candidates";
public static final String DEFAULT_INIT_METHOD_ATTRIBUTE = "default-init-method";
public static final String DEFAULT_DESTROY_METHOD_ATTRIBUTE = "default-destroy-method";
private BeanDefinitionRegistry registry;
public BeanDefinitionParserDelegate(BeanDefinitionRegistry registry) {
this.registry = registry;
}
public void parseDocumentRegisterBeanDefinition(Document document) throws Exception {
NodeList beanNodes = document.getElementsByTagName(BEAN_ELEMENT);
for (int i = 0; i < beanNodes.getLength(); i++) {
Node beanNode = beanNodes.item(i);
if (beanNode.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) beanNode;
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
String beanName = this.parseBeanDefinitionElement(element, beanDefinition);
this.registry.registerBeanDefinition(beanName, beanDefinition);
}
}
}
private String parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition beanDefinition) throws Exception {
// 解析id属性,也就是BeanName
String beanName = ele.getAttribute(ID_ATTRIBUTE);
String className = ele.getAttribute(CLASS_ATTRIBUTE);
String initMethod = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
String destroyMethod = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
beanDefinition.setBeanClass(this.getClass().getClassLoader().loadClass(className));
beanDefinition.setInitMethodName(initMethod);
beanDefinition.setDestroyMethodName(destroyMethod);
this.parseConstructorArgElements(ele, beanDefinition);
NodeList constructorArgsList = ele.getElementsByTagName(CONSTRUCTOR_ARG_ELEMENT);
List<Object> constructorArgumentValues = new ArrayList<>();
for (int j = 0; j < constructorArgsList.getLength(); j++) {
Element argElement = (Element) constructorArgsList.item(j);
String argType = argElement.getAttribute("type");
String value = argElement.getAttribute("value");
if (StringUtils.isNotBlank(value)) {
constructorArgumentValues.add(value);
} else if (argElement.hasAttribute("ref")) {
String refName = argElement.getAttribute("ref");
constructorArgumentValues.add(new BeanReference(refName));
}
}
beanDefinition.setConstructorArgumentValues(constructorArgumentValues);
return beanName;
}
private void parseConstructorArgElements(Element beanEle, BeanDefinition beanDefinition) {
List<Object> constructorArgumentValues = new ArrayList<>();
NodeList constructorArgsList = beanEle.getElementsByTagName(CONSTRUCTOR_ARG_ELEMENT);
for (int i = 0; i < constructorArgsList.getLength(); i++) {
Element argElement = (Element) constructorArgsList.item(i);
String value = argElement.getAttribute(VALUE_ATTRIBUTE);
if (StringUtils.isNotBlank(value)) {
constructorArgumentValues.add(value);
} else if (argElement.hasAttribute(REF_ATTRIBUTE)) {
String refName = argElement.getAttribute(REF_ATTRIBUTE);
constructorArgumentValues.add(new BeanReference(refName));
}
beanDefinition.setConstructorArgumentValues(constructorArgumentValues);
}
}
}
2、基于注解
类似下面这种,通过注解实现AOP和DI
@Component
public class ForlanController{
@Autowired
private Forlan forlan;
}
思路
定义一套注解
写代码来扫描、解析注解,完成Bean定义注册
1)定义相关注解
- @Component:标记类为Bean
- @Scope:Bean作用域
- @Primary:多个Bean的情况下,默认注入的Bean
- @Bean:注册Bean对象
- @PostConstruct:初始化方法
- @PreDestory:销毁方法
- @Autowired:依赖注入
- @Value:属性依赖
- @Qualifier:属性依赖
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {
String value() default "";
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {
String value() default BeanDefinition.SCOPE_SINGLETON;
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Primary {
}
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
String initMethod() default "";
String destroyMethod() default "";
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PostConstruct {
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PreDestroy {
}
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {
String value();
}
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
String value() default "";
}
2)扫描包下的所有被@Componment修饰的Java类,生成BeanDefinition,注册到BeanFactory
实现以scan为核心方法的代码,主要包括递归扫描包目录下的.class文件、根据Class对象,解析注解,转为BeanDefintion,注册到BeanFactory中,具体代码如下:
public class ClassPathBeanDefinitionScanner {
// 当在开发时执行单元测试,测试类是另一个类目录,这里可能有点问题,其它暂时没发现问题
private static final int classResourceAbsolutePathIndex = new File(new File(ClassPathBeanDefinitionScanner.class.getResource("/").getPath()).getAbsolutePath()).getAbsolutePath().length();
// 匹配数字的正则表达式,目前用于把@Value的字符串转为数字
private static final String regex = "\\#\\{(\\d+)\\}";
private BeanDefinitionRegistry registry;
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
this.registry = registry;
}
public void scan(String... basePackages) throws Exception {
if (basePackages != null && basePackages.length > 0) {
for (String basePackage : basePackages) {
// 1、递归扫描包目录下的.class文件
Set<File> classFiles = this.doScan(basePackage);
// 2、根据Class对象,解析注解,转为BeanDefintion,注册到BeanFactory中
this.readAndRegisterBeanDefintion(classFiles);
}
}
}
/**
* 扫描指定包下的所有类
*/
private Set<File> doScan(String basePackage) throws IOException {
// 将包名转为路径名
String basePackagePath = "/" + StringUtils.replace(basePackage, ".", "/");
// 得到包对应的目录
File rootDir = new File(this.getClass().getResource(basePackagePath).getPath());
// 存放找到的类文件的集合
Set<File> scanedClassFiles = new HashSet<>();
// 扫描class文件,存到scanedClassFiles中
this.doRetrieveClassFiles(rootDir, scanedClassFiles);
return scanedClassFiles;
}
/**
* 递归查找指定目录下的所有类,查找规则:.class结尾。
*/
protected void doRetrieveClassFiles(File dir, Set<File> result) throws IOException {
for (File file : dir.listFiles()) {
if (file.isDirectory() && file.canRead()) {
doRetrieveClassFiles(file, result);
}
if (file.getName().endsWith(".class")) {
result.add(file);
}
}
}
private void readAndRegisterBeanDefintion(Set<File> classFiles) throws Exception {
for (File classFile : classFiles) {
// 得到根路径:cn.forlan.aop.beans.sample.xxx
String className = getClassNameFromFile(classFile);
// 加载类
Class<?> clazz = this.getClass().getClassLoader().loadClass(className);
// 只处理@Component注解的类
Component component = clazz.getAnnotation(Component.class);
if (component == null) {
continue;
}
// 没有指定名字的话,则把驼峰类名作为名字
String beanName = component.value();
if (StringUtils.isBlank(beanName)) {
beanName = this.generateBeanName(clazz);
}
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(clazz);
// 处理Scope
Scope scope = clazz.getAnnotation(Scope.class);
if (scope != null) {
beanDefinition.setScope(scope.value());
}
// 处理Primary
Primary primary = clazz.getAnnotation(Primary.class);
if (primary != null) {
beanDefinition.setPrimary(true);
}
// 处理构造方法,找出加了@Autowired注解的构造方法,将这个构造方法设置到beanDefinition中
this.handleConstructor(clazz, beanDefinition);
// 处理方法上的注解(找出初始化、销毁、工厂方法)
this.handleMethod(clazz, beanDefinition, beanName);
// 处理属性依赖
this.handlePropertyDI(clazz, beanDefinition);
// 注册bean定义
this.registry.registerBeanDefinition(beanName, beanDefinition);
}
}
private String getClassNameFromFile(File classFile) {
// 例如,G:\ideaProject\ceshi\forlan-spring\target\classes\cn\forlan\aop\beans\sample\Forlan.class
String absolutePath = classFile.getAbsolutePath();
// 例如,cn\forlan\aop\beans\sample\Forlan.class
String classNameWithPackage = absolutePath.substring(classResourceAbsolutePathIndex + 1);
// 例如,cn\forlan\aop\beans\sample\Forlan
String name = classNameWithPackage.replace(".class", "");
// 例如,cn.forlan.aop.beans.sample.Forlan
return StringUtils.replace(name, File.separator, ".");
}
/**
* 首字母小写
*/
private String generateBeanName(Class<?> clazz) {
String simpleName = clazz.getSimpleName();
// return simpleName.substring(0, 1).toLowerCase() + simpleName.substring(1);
return Character.toLowerCase(simpleName.charAt(0)) + simpleName.substring(1);
}
private void handleConstructor(Class<?> clazz, GenericBeanDefinition beanDefinition) {
Constructor<?>[] constructors = clazz.getConstructors();
if (constructors == null || constructors.length == 0) {
return;
}
for (Constructor<?> constructor : constructors) {
if (constructor.isAnnotationPresent(Autowired.class)) {
beanDefinition.setConstructor(constructor);
// 处理设置构造参数
beanDefinition.setConstructorArgumentValues(this.handleParameter(constructor.getParameters()));
break;
}
}
}
private List<Object> handleParameter(Parameter[] parameters) {
List<Object> res = new ArrayList<>();
for (Parameter parameter : parameters) {
Value valueAnnotation = parameter.getAnnotation(Value.class);
if (valueAnnotation != null) {
String value = valueAnnotation.value();
if (value.contains("#{")) {
value = value.replaceAll(regex, "$1");
res.add(Integer.parseInt(value));
} else {
res.add(value);
}
continue;
}
Qualifier qualifier = parameter.getAnnotation(Qualifier.class);
if (qualifier != null) {
res.add(new BeanReference(qualifier.value()));
} else {
res.add(new BeanReference(parameter.getType()));
}
}
return res;
}
private void handleMethod(Class<?> clazz, GenericBeanDefinition beanDefinition, String beanName) throws Exception {
for (Method method : clazz.getMethods()) {
if (method.isAnnotationPresent(PostConstruct.class)) {
beanDefinition.setInitMethodName(method.getName());
} else if (method.isAnnotationPresent(PreDestroy.class)) {
beanDefinition.setDestroyMethodName(method.getName());
} else if (method.isAnnotationPresent(Bean.class)) {
this.handleFactoryMethod(clazz, beanName, method);
}
}
}
private void handleFactoryMethod(Class<?> clazz, String beanName, Method method) throws Exception {
BeanDefinition beanDefinition = new GenericBeanDefinition();
if (Modifier.isStatic(method.getModifiers())) {
beanDefinition.setBeanClass(clazz);
} else {
beanDefinition.setFactoryBeanName(beanName);
}
beanDefinition.setFactoryMethod(method);
beanDefinition.setFactoryMethodName(method.getName());
//处理Scope
Scope scope = method.getAnnotation(Scope.class);
if (scope != null) {
beanDefinition.setScope(scope.value());
}
//处理Primary
Primary primary = method.getAnnotation(Primary.class);
if (primary != null) {
beanDefinition.setPrimary(true);
}
// 处理Bean
Bean bean = method.getAnnotation(Bean.class);
String targetBeanName = bean.name();
if (StringUtils.isBlank(targetBeanName)) {
targetBeanName = method.getName();
}
// 设置初始化方法、销毁方法
if (StringUtils.isNotBlank(bean.initMethod())) {
beanDefinition.setInitMethodName(bean.initMethod());
}
if (StringUtils.isNotBlank(bean.destroyMethod())) {
beanDefinition.setDestroyMethodName(bean.destroyMethod());
}
// 处理设置构造参数
beanDefinition.setConstructorArgumentValues(this.handleParameter(method.getParameters()));
// 注册BeanDefinition
this.registry.registerBeanDefinition(targetBeanName, beanDefinition);
}
private void handlePropertyDI(Class<?> clazz, GenericBeanDefinition beanDefinition) {
List<PropertyValue> propertyValues = new ArrayList<>();
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Autowired.class)) {
Qualifier qualifier = field.getAnnotation(Qualifier.class);
BeanReference reference = null;
if (qualifier != null) {
reference = new BeanReference(qualifier.value());
} else {
reference = new BeanReference(field.getType());
}
propertyValues.add(new PropertyValue(field.getName(), reference));
}
}
beanDefinition.setPropertyValues(propertyValues);
}
}
三、优化
通过上面的实现,给用户的体验还不是很友好,搞一个门面模式,定义一个简单的统一使用界面,引入了ApplicationContext
定义一个上下文接口,继承BeanFactory接口
public interface ApplicationContext extends BeanFactory {
}
定义一个公共抽象上下文对象,实现ApplicationContext接口,同时提供重写BeanFactory的方法
public abstract class AbstractApplicationContext implements ApplicationContext {
protected DefaultBeanFactory beanFactory;
public AbstractApplicationContext() {
super();
this.beanFactory = new DefaultBeanFactory();
}
protected void refresh() throws Exception {
// 在registerBeanDefinition方法里面已经调用了,也可以抽取到这里调用
// beanFactory.registerTypeNameMap();
// 注册BeanPostProcessor
doRegisterBeanPostProcessor();
}
private void doRegisterBeanPostProcessor() throws Exception {
// 从BeanFactory中得到所有用户配置的BeanPostProcessor类型的Bean实例,注册到BeanFactory
List<BeanPostProcessor> beanPostProcessors = beanFactory.getBeansOfTypeList(BeanPostProcessor.class);
if (CollectionUtils.isNotEmpty(beanPostProcessors)) {
for (BeanPostProcessor bpp : beanPostProcessors) {
beanFactory.registerBeanPostProcessor(bpp);
}
}
}
@Override
public Object getBean(String name) throws Exception {
return this.beanFactory.getBean(name);
}
@Override
public Class<?> getType(String name) throws Exception {
return this.beanFactory.getType(name);
}
@Override
public <T> T getBean(Class<T> requiredType) throws Exception {
return this.beanFactory.getBean(requiredType);
}
@Override
public <T> Map<String, T> getBeansOfType(Class<T> type) throws Exception {
return this.beanFactory.getBeansOfType(type);
}
@Override
public <T> List<T> getBeansOfTypeList(Class<T> type) throws Exception {
return this.beanFactory.getBeansOfTypeList(type);
}
@Override
public void registerBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
this.beanFactory.registerBeanPostProcessor(beanPostProcessor);
}
}
实现一个关于注解的上下文对象
public class AnnotationApplicationContext extends AbstractApplicationContext {
public AnnotationApplicationContext(String... basePackages) throws Exception {
super();
// 找到所有被@Componment修饰的Java类,生成BeanDefinition,注册到BeanFactory
new ClassPathBeanDefinitionScanner((BeanDefinitionRegistry) this.beanFactory).scan(basePackages);
super.refresh();
}
}
实现一个关于xml配置的上下文对象
public class XmlApplicationContext extends AbstractApplicationContext {
public XmlApplicationContext(String filePath) throws Exception {
super();
// 加载解析xml配置,生成BeanDefinition,注册BeanFactory
new XmlBeanDefinitionReader((BeanDefinitionRegistry) this.beanFactory).loadBeanDefinitions(filePath);
super.refresh();
}
}
四、总结
通过上面的注解或xml配置,加上门面模式,现在代码就变得很简单了,如下:
1、注解
只需要在相关的类、方法、字段加上注解
@Component
public class ForlanFactory {
@Bean
public static Forlan getForlanByStaticMethod(@Value("静态工厂方法") String name, @Value("#{15}") Integer age) {
return new Forlan(name, age);
}
@Bean
@Primary
public Forlan getForlan(@Value("工厂bean方式") String name, @Value("#{20}") Integer age, @Qualifier("forlanA") ForlanA forlanA) {
return new Forlan(name, age, forlanA);
}
}
使用的话,直接创建一个上下文对象,内部的构造方法就会自动扫描注册Bean定义信息到BeanFactory,我们就可以直接获取到相关的Bean
public static void testRegistBeanByAnnotation() throws Exception {
ApplicationContext context = new AnnotationApplicationContext("cn.forlan.aop.beans.sample");
ForlanA forlanA = (ForlanA) context.getBean("forlanA");
forlanA.introduceAll();
}
public static void testRegistBeanByStaticFactoryMethodByAnnotation() throws Exception {
ApplicationContext context = new AnnotationApplicationContext("cn.forlan.aop.beans.sample");
Forlan forlan = (Forlan) context.getBean("getForlanByStaticMethod");
forlan.introduce0();
}
public static void testRegistBeanByFactoryMethodByAnnotation() throws Exception {
ApplicationContext context = new AnnotationApplicationContext("cn.forlan.aop.beans.sample");
Forlan forlan = (Forlan) context.getBean("getForlan");
forlan.introduce0();
}
public static void testRegistComplexBeanByAnnotation() throws Exception {
ApplicationContext context = new AnnotationApplicationContext("cn.forlan.aop.beans.sample");
Forlan forlan = (Forlan) context.getBean(Forlan.class);
forlan.introduce0();
}
2、xml配置
新增forlan.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="forlanA" class="cn.forlan.aop.beans.sample.ForlanA" init-method="init" destroy-method="destroy">
<constructor-arg type="java.lang.String" value="程序员3"/>
<constructor-arg ref="forlanAA"/>
</bean>
<bean id="forlanAA" class="cn.forlan.aop.beans.sample.ForlanAA" init-method="init" destroy-method="destroy">
<constructor-arg type="java.lang.String" value="程序员4"/>
</bean>
</beans>
使用的话,直接创建一个上下文对象,内部的构造方法就会自动解析配置为Bean定义信息到BeanFactory,我们就可以直接获取到相关的Bean
public static void testRegistBeanByXml() throws Exception {
ApplicationContext context = new XmlApplicationContext("G:\\ideaProject\\ceshi\\forlan-spring\\src\\main\\resources\\forlan.xml");
ForlanA forlanA = (ForlanA) context.getBean("forlanA");
forlanA.introduceAll();
}
标签:String,Spring,final,Bean,源码,static,new,public,beanDefinition
From: https://blog.csdn.net/qq_36433289/article/details/135904020