当前位置: 首页 > news >正文

怎么做网站信任asp.net网站开发流程

怎么做网站信任,asp.net网站开发流程,高级wordpress搜索引擎,怎么改网站关键词Spring源码之手写DI 我们来回顾一下前面手写IOC的内容。 一、DI介绍 DI(Dependency injection)依赖注入。对象之间的依赖由容器在运行期决定#xff0c;即容器动态的将某个依赖注入到对象之中。说直白点就是给Bean对象的成员变量赋值。 在这里我们就需要明白几个问题。 1.…Spring源码之手写DI 我们来回顾一下前面手写IOC的内容。 一、DI介绍 DI(Dependency injection)依赖注入。对象之间的依赖由容器在运行期决定即容器动态的将某个依赖注入到对象之中。说直白点就是给Bean对象的成员变量赋值。 在这里我们就需要明白几个问题。 1. 哪些地方会有依赖 构造参数依赖属性依赖 2. 依赖注入的本质是什么 依赖注入的本质是 赋值。赋值有两种情况 给有参构造方法赋值给属性赋值 3. 参数值、属性值有哪些 具体赋值有两种情况直接值和Bean依赖。比如 public clsss Girl{public Girl(String name, int age, Clouth clouth){private String name;private Integer age;private Clothes clothes;} }4. 直接赋值有哪些 基本数据类型String、int 等数组集合map 二、构造注入 我们先来看看构造参数注入的情况应该要如何解决。 1.构造注入分析 我们应该如何定义构造参数的依赖也就是我们需要通过构造方法来创建实例然后对应的构造方法我们需要传入对应的参数。如果不是通过IoC来处理我们可以直接通过如下的代码实现。 public static void main(String[] args) {Clouth clouth new Dress();Girl girl new Girl(小龙女, 18, clouth);}我们通过直接赋值的方式就可以了。但是在IOC中我们需要通过反射的方式来进行通用处理。在使用反射操作的时候就需要能获取到对应的构造参数的依赖了这时我们得分析怎么来存储我们的构造参数的依赖了。构造参数的依赖有两个特点 顺序数量类型 上面例子中构造函数的参数 小丽 String类型20 int 类型clouth 自定义的Clouth类型是一个依赖Bean 参数可以有多个我们可以通过List集合来存储这样构造参数的顺序就可以通过控制往List集合中add元素的顺来保证。但是需要注意的是依赖Bean如何表示呢 基本类型的值直接添加到集合中就可以了但是依赖Bean的实例对象可能还没有创建那么这时我们可以抽象出一个类用来描述依赖Bean的信息。 2. BeanReference 注意 BeanReference其实就是用来描述依赖Bean信息的 /*** 用于依赖注入中描述bean依赖*/ public class BeanReference {private String beanName;private Class? type;public BeanReference(Class? type) {this.type type;}public String getBeanName() {return beanName;}public void setBeanName(String beanName) {this.beanName beanName;}public Class? getType() {return type;}public void setType(Class? type) {this.type type;} } 可以根据name来依赖也可以按照Type来依赖。另外还有一点需要考虑就是如何来区分是直接值还是依赖Bean呢有了上面的设计其实就很容易判断了。 if ( obj instanceOf BeanReference)但是下面这种直接值是数组或者集合等同时容器中的元素是依赖Bean的情况 import java.io.Serializable; import java.util.List;public class Girl implements Serializable {private String name;private Integer age;private ListClothes clothesList;public Girl(String name, Integer age, ListClothes clothesList) {this.name name;this.age age;this.clothesList clothesList;} }这种情况下元素值仍然可以用BeanReference来处理。Bean工厂在处理时需要遍历替换。 3. BeanDefinition实现 接下来我们看看如何具体的来实现DI基于构造函数参数依赖的相关操作。首先是BeanDefinition定义的相关处理。需要在 BeanDefinition中增加构造参数的获取的方法。 然后我们需要在默认的实现GenericBeanDefinition中增加对应的方法来处理。 BeanDefinition接口 import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.List;import org.apache.commons.lang3.StringUtils;/*** bean定义接口*/ public interface BeanDefinition {String SCOPE_SINGLETON singleton;String SCOPE_PROTOTYPE prototype;/*** 类*/Class? getBeanClass();/*** Scope*/String getScope();/*** 是否单例*/boolean isSingleton();/*** 是否原型*/boolean isPrototype();/*** 工厂bean名*/String getFactoryBeanName();/*** 工厂方法名*/String getFactoryMethodName();/*** 初始化方法*/String getInitMethodName();/*** 销毁方法*/String getDestroyMethodName();boolean isPrimary();/*** 校验bean定义的合法性*/default boolean validate() {// 没定义class,工厂bean或工厂方法没指定则认为不合法。if (this.getBeanClass() null) {if (StringUtils.isBlank(getFactoryBeanName()) || StringUtils.isBlank(getFactoryMethodName())) {return false;}}// 定义了类又定义工厂bean不合法if (this.getBeanClass() ! null StringUtils.isNotBlank(getFactoryBeanName())) {return false;}return true;}/*** 获得构造参数定义*/List? getConstructorArgumentValues();/*** 属性依赖*/ListPropertyValue getPropertyValues();/*** 下面的四个方法是供beanFactory中使用的*/public Constructor? getConstructor();public void setConstructor(Constructor? constructor);public Method getFactoryMethod();public void setFactoryMethod(Method factoryMethod);}BeanDefinition的通用实现GernericBeanDefinition import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.List;import org.apache.commons.lang3.StringUtils;public class GenericBeanDefinition implements BeanDefinition {private Class? beanClass;private String scope BeanDefinition.SCOPE_SINGLETON;private String factoryBeanName;private String factoryMethodName;private String initMethodName;private String destroyMethodName;private boolean primary;private Constructor? constructor;private Method factoryMethod;private List? constructorArgumentValues;private ListPropertyValue propertyValues;public void setBeanClass(Class? beanClass) {this.beanClass beanClass;}public void setScope(String scope) {if (StringUtils.isNotBlank(scope)) {this.scope scope;}}public void setFactoryBeanName(String factoryBeanName) {this.factoryBeanName factoryBeanName;}public void setFactoryMethodName(String factoryMethodName) {this.factoryMethodName factoryMethodName;}public void setInitMethodName(String initMethodName) {this.initMethodName initMethodName;}public void setDestroyMethodName(String destroyMethodName) {this.destroyMethodName destroyMethodName;}Overridepublic Class? getBeanClass() {return this.beanClass;}Overridepublic String getScope() {return this.scope;}Overridepublic boolean isSingleton() {return BeanDefinition.SCOPE_SINGLETON.equals(this.scope);}Overridepublic boolean isPrototype() {return BeanDefinition.SCOPE_PROTOTYPE.equals(this.scope);}Overridepublic String getFactoryBeanName() {return this.factoryBeanName;}Overridepublic String getFactoryMethodName() {return this.factoryMethodName;}Overridepublic String getInitMethodName() {return this.initMethodName;}Overridepublic String getDestroyMethodName() {return this.destroyMethodName;}public void setPrimary(boolean primary) {this.primary primary;}Overridepublic boolean isPrimary() {return this.primary;}public List? getConstructorArgumentValues() {return constructorArgumentValues;}public void setConstructorArgumentValues(List? constructorArgumentValues) {this.constructorArgumentValues constructorArgumentValues;}public ListPropertyValue getPropertyValues() {return propertyValues;}public void setPropertyValues(ListPropertyValue propertyValues) {this.propertyValues propertyValues;}public Constructor? getConstructor() {return constructor;}public void setConstructor(Constructor? constructor) {this.constructor constructor;}public Method getFactoryMethod() {return factoryMethod;}public void setFactoryMethod(Method factoryMethod) {this.factoryMethod factoryMethod;}Overridepublic String toString() {return GenericBeanDefinition [beanClass beanClass , scope scope , factoryBeanName factoryBeanName , factoryMethodName factoryMethodName , initMethodName initMethodName , destroyMethodName destroyMethodName ];}Overridepublic int hashCode() {final int prime 31;int result 1;result prime * result ((beanClass null) ? 0 : beanClass.hashCode());result prime * result ((destroyMethodName null) ? 0 : destroyMethodName.hashCode());result prime * result ((factoryBeanName null) ? 0 : factoryBeanName.hashCode());result prime * result ((factoryMethodName null) ? 0 : factoryMethodName.hashCode());result prime * result ((initMethodName null) ? 0 : initMethodName.hashCode());result prime * result ((scope null) ? 0 : scope.hashCode());return result;}Overridepublic boolean equals(Object obj) {if (this obj)return true;if (obj null)return false;if (getClass() ! obj.getClass())return false;GenericBeanDefinition other (GenericBeanDefinition) obj;if (beanClass null) {if (other.beanClass ! null)return false;} else if (!beanClass.equals(other.beanClass))return false;if (destroyMethodName null) {if (other.destroyMethodName ! null)return false;} else if (!destroyMethodName.equals(other.destroyMethodName))return false;if (factoryBeanName null) {if (other.factoryBeanName ! null)return false;} else if (!factoryBeanName.equals(other.factoryBeanName))return false;if (factoryMethodName null) {if (other.factoryMethodName ! null)return false;} else if (!factoryMethodName.equals(other.factoryMethodName))return false;if (initMethodName null) {if (other.initMethodName ! null)return false;} else if (!initMethodName.equals(other.initMethodName))return false;if (scope null) {if (other.scope ! null)return false;} else if (!scope.equals(other.scope))return false;return true;}} 定义后我们来测试一下对应的应用定义个TestOneBean依赖了TestTwoBean public class TestOneBean {private String name;private TestTwoBean testTwoBean;public TestOneBean(String name, TestTwoBean testTwoBean) {super();this.name name;this.testTwoBean testTwoBean;System.out.println(调用了含有TestTwoBean参数的构造方法);}public TestOneBean(String name, TestThreeBean testThreeBean) {super();this.name name;this.testThreeBean testThreeBean;System.out.println(调用了含有TestThreeBean参数的构造方法);}public ABean(TestTwoBean testTwoBean) {super();this.testTwoBean testTwoBean;}public void doSomthing() {System.out.println(String.format(TestOneBean.doSomthing(): %s TestOneBean.name %s, this.name, this.testTwoBean.getName()));}public void init() {System.out.println(TestOneBean.init() 执行了);}public void destroy() {System.out.println(TestOneBean.destroy() 执行了);} } 然后在实例化时我们需要做相关的绑定 GenericBeanDefinition bd new GenericBeanDefinition(); bd.setBeanClass(TestOneBean.class); // 定义的构造参数的依赖 ListObject args new ArrayList(); args.add(testOneBean); // 依赖Bean 通过BeanReference来处理 args.add(new BeanReference(testTwoBean)); bd.setConstructorArgumentValues(args); bf.registerBeanDefinition(testOneBean, bd);构造参数传递后接下来需要在 BeanFactory中来实现构造参数的注入了 4.BeanFactory实现 前面我们在BeanFactory中实现Bean对象的创建有几种方式 构造方法创建工厂静态方法工厂成员方法 import java.util.Map;public interface BeanFactory {Object getBean(String name) throws Exception;T T getBean(ClassT type)throws Exception;T MapString,T getBeansOfType(ClassT type)throws Exception;Class? getType(String name) throws Exception; }BeanFactory的默认实现DefaultBeanFactory import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils;import java.io.Closeable; import java.io.IOException; import java.lang.reflect.*; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap;/*** 1.构造参数依赖注入的 参数真实值获取实现构造方法方式的构造方法的判定实现* 2.缓存原型bean的构造方法、工厂方法增加了 静态工厂方法、工厂bean工厂方法的参数依赖实现* 3.构造循环依赖检测* 4.属性依赖实现*/ Slf4j public class DefaultBeanFactory implements BeanFactory, BeanDefinitionRegistry, Closeable {protected MapString, BeanDefinition beanDefintionMap new ConcurrentHashMap(256);private final MapString, Object singletonBeanMap new ConcurrentHashMap(256);private final MapClass?, SetString typeMap new ConcurrentHashMap(256);private final ThreadLocalSetString buildingBeansRecorder new ThreadLocal();/*** Spring 中属性依赖的情况 如果循环依赖中不存在单例则不可以否则可以*/private final ThreadLocalMapString, Object earlyExposeBuildingBeans new ThreadLocal();Overridepublic void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionRegistException {Objects.requireNonNull(beanName, 注册bean需要指定beanName);Objects.requireNonNull(beanDefinition, 注册bean需要指定beanDefinition);// 校验给入的bean是否合法if (!beanDefinition.validate()) {throw new BeanDefinitionRegistException(名字为[ beanName ] 的bean定义不合法 beanDefinition);}if (this.containsBeanDefinition(beanName)) {throw new BeanDefinitionRegistException(名字为[ beanName ] 的bean定义已存在: this.getBeanDefinition(beanName));}this.beanDefintionMap.put(beanName, beanDefinition);}public void registerTypeMap() throws Exception {for (String name : this.beanDefintionMap.keySet()) {Class? type this.getType(name);//映射本类this.registerTypeMap(name, type);//父类this.registerSuperClassTypeMap(name, type);//接口this.registerInterfaceTypeMap(name, type);}}private void registerInterfaceTypeMap(String name, Class? type) {Class?[] interfaces type.getInterfaces();for (Class? interfaceClasses : interfaces) {this.registerTypeMap(name, interfaceClasses);//递归找父接口this.registerInterfaceTypeMap(name, interfaceClasses);}}private void registerSuperClassTypeMap(String name, Class? type) {Class? superClass type.getSuperclass();if (superClass ! null !superClass.equals(Object.class)) {this.registerTypeMap(name, superClass);//递归找父类this.registerSuperClassTypeMap(name, superClass);//找父类实现的接口注册this.registerInterfaceTypeMap(name, superClass);}}private void registerTypeMap(String name, Class? type) {SetString names2type this.typeMap.computeIfAbsent(type, k - new HashSet());names2type.add(name);}Overridepublic Class? getType(String name) throws Exception {BeanDefinition beanDefinition this.getBeanDefinition(name);Class? type beanDefinition.getBeanClass();if (type ! null) {if (StringUtils.isBlank(beanDefinition.getFactoryMethodName())) {// 构造方法来构造对象的Type就是beanClass,不需做什么。} else {// 静态工厂方法方式的反射获得Method,再获取Method的返回值类型type type.getDeclaredMethod(beanDefinition.getFactoryMethodName(), null).getReturnType();}} else {// 获得工厂Bean的Classtype this.getType(beanDefinition.getFactoryBeanName());// 获取工厂方法的返回值类型type type.getDeclaredMethod(beanDefinition.getFactoryMethodName(), null).getReturnType();}return type;}Overridepublic BeanDefinition getBeanDefinition(String beanName) {return this.beanDefintionMap.get(beanName);}Overridepublic boolean containsBeanDefinition(String beanName) {return this.beanDefintionMap.containsKey(beanName);}Overridepublic Object getBean(String name) throws Exception {return this.doGetBean(name);}Overridepublic T T getBean(ClassT type) throws Exception {/** 逻辑* 1. 获取其对应的所有的BeanDefinition* 2. 如果只有一个直接获取bean实例返回否则* 3. 遍历找出Primary的* 4. 如果primary没有或大于1个抛出异常* 5. 返回Primary的实例*/SetString names this.typeMap.get(type);if (names ! null) {if (names.size() 1) {return (T) this.getBean(names.iterator().next());} else {//找PrimaryBeanDefinition beanDefinition null;String primaryName null;StringBuilder nameStrings new StringBuilder();for (String name : names) {beanDefinition this.getBeanDefinition(name);if (beanDefinition ! null beanDefinition.isPrimary()) {if (primaryName ! null) {String mess type 类型的Bean存储多个Primary[ primaryName , name ];log.error(mess);throw new Exception(mess);} else {primaryName name;}}nameStrings.append( ).append(name);}if (primaryName ! null) {return (T) this.getBean(primaryName);} else {String mess type 类型的Bean存在多个[ nameStrings ] 但无法确定Primary;log.error(mess);throw new Exception(mess);}}}return null;}Overridepublic T MapString, T getBeansOfType(ClassT type) throws Exception {SetString names this.typeMap.get(type);if (names ! null) {MapString, T map new HashMap();for (String name : names) {map.put(name, (T) this.getBean(name));}return map;}return null;}protected Object doGetBean(String beanName) throws Exception {Objects.requireNonNull(beanName, beanName不能为空);Object instance singletonBeanMap.get(beanName);if (instance ! null) {return instance;}instance this.getFromEarlyExposeBuildingBeans(beanName);if (instance ! null) { //这是属性依赖时的循环引用返回提前暴露的实例return instance;}BeanDefinition beanDefinition this.getBeanDefinition(beanName);Objects.requireNonNull(beanDefinition, beanDefinition不能为空);// 检测构造参数循环依赖SetString buildingBeans this.buildingBeansRecorder.get();if (buildingBeans null) {buildingBeans new HashSet();this.buildingBeansRecorder.set(buildingBeans);}if (buildingBeans.contains(beanName)) {throw new Exception(beanName 循环依赖 buildingBeans);}// 记录正在创建的BeanbuildingBeans.add(beanName);if (beanDefinition.isSingleton()) { //如果是单例synchronized (this.singletonBeanMap) { //加锁instance this.singletonBeanMap.get(beanName);if (instance null) {//第二次检查instance doCreateInstance(beanName, beanDefinition);this.singletonBeanMap.put(beanName, instance);}}} else {instance doCreateInstance(beanName, beanDefinition);}// 创建好实例后移除创建中记录buildingBeans.remove(beanName);return instance;}private Object getFromEarlyExposeBuildingBeans(String beanName) {MapString, Object earlyExposeBuildingBeansMap earlyExposeBuildingBeans.get();return earlyExposeBuildingBeansMap null ? null : earlyExposeBuildingBeansMap.get(beanName);}private Object doCreateInstance(String beanName, BeanDefinition beanDefinition) throws Exception {Class? type beanDefinition.getBeanClass();Object instance;if (type ! null) {if (StringUtils.isBlank(beanDefinition.getFactoryMethodName())) {// 构造方法来构造对象instance this.createInstanceByConstructor(beanDefinition);} else {// 静态工厂方法instance this.createInstanceByStaticFactoryMethod(beanDefinition);}} else {// 工厂bean方式来构造对象instance this.createInstanceByFactoryBean(beanDefinition);}this.doEarlyExposeBuildingBeans(beanName, instance);// 给入属性依赖this.setPropertyDIValues(beanDefinition, instance);this.removeEarlyExposeBuildingBeans(beanName, instance);// 执行初始化方法this.doInit(beanDefinition, instance);return instance;}private void removeEarlyExposeBuildingBeans(String beanName, Object instance) {earlyExposeBuildingBeans.get().remove(beanName);}private void doEarlyExposeBuildingBeans(String beanName, Object instance) {MapString, Object earlyExposeBuildingBeansMap earlyExposeBuildingBeans.get();if (earlyExposeBuildingBeansMap null) {earlyExposeBuildingBeansMap new HashMap();earlyExposeBuildingBeans.set(earlyExposeBuildingBeansMap);}earlyExposeBuildingBeansMap.put(beanName, instance);}// 给入属性依赖private void setPropertyDIValues(BeanDefinition bd, Object instance) throws Exception {if (CollectionUtils.isEmpty(bd.getPropertyValues())) {return;}for (PropertyValue pv : bd.getPropertyValues()) {if (StringUtils.isBlank(pv.getName())) {continue;}Class? clazz instance.getClass();Field p clazz.getDeclaredField(pv.getName());p.setAccessible(true);p.set(instance, this.getOneArgumentRealValue(pv.getValue()));}}/*** 构造方法来构造对象** param beanDefinition bean定义* return bean实例对象* throws Exception 异常*/private Object createInstanceByConstructor(BeanDefinition beanDefinition)throws Exception {/*构造参数依赖注入这里需要做些什么1 得到真正的参数值因为List? constructorArgumentValues beanDefinition.getConstructorArgumentValues();constructorArgumentValues 中可能有 BeanReference*/Object[] args this.getConstructorArgumentValues(beanDefinition);// 2 判定应该调用哪个构造方法来创建实例return this.determineConstructor(beanDefinition, args).newInstance(args);}private Object[] getConstructorArgumentValues(BeanDefinition bd) throws Exception {List? constructorArgumentValues bd.getConstructorArgumentValues();if (CollectionUtils.isEmpty(constructorArgumentValues)) {return null;}Object[] values new Object[constructorArgumentValues.size()];int i 0;for (Object originalValue : constructorArgumentValues) {values[i] getOneArgumentRealValue(originalValue); //获取真正参数值的逻辑应该是怎样的}return values;}private Object getOneArgumentRealValue(Object originalValue) throws Exception {//获取真正参数值主要是处理BeanReference,得到真正的Bean实例Object realValue null;if (originalValue ! null) {if (originalValue instanceof BeanReference) {BeanReference beanReference (BeanReference) originalValue;if (StringUtils.isNotBlank(beanReference.getBeanName())) {realValue this.getBean(beanReference.getBeanName());} else if (beanReference.getType() ! null) {realValue this.getBean(beanReference.getType());}} else if (originalValue instanceof Object[]) {// 处理数组中的bean引用Object[] originalValueNew (Object[]) originalValue;for (int i 0; i originalValueNew.length; i) {Object attr originalValueNew[i];Class? attrClass attr.getClass();String simpleName attrClass.getSimpleName();BeanReference beanReference new BeanReference(attrClass);beanReference.setBeanName(getBeanName(simpleName));originalValueNew[i] beanReference;}realValue originalValueNew;} else if (originalValue instanceof Collection) {// 处理集合中的bean引用Type genericSuperclass originalValue.getClass().getGenericSuperclass();Class? extends Type genericClass genericSuperclass.getClass();BeanReference beanReference new BeanReference(genericClass);String simpleName genericClass.getSimpleName();String beanName getBeanName(simpleName);beanReference.setBeanName(beanName);CollectionBeanReference originalValueNew new ArrayList();originalValueNew.add(beanReference);realValue originalValueNew;} else if (originalValue instanceof Properties) {// 处理properties中的bean引用Properties originValueNew new Properties();originValueNew.put(new BeanReference(null), new BeanReference(null));realValue originValueNew;} else if (originalValue instanceof Map) {// 处理Map中的bean引用MapBeanReference, BeanReference originValueNew new HashMap();originValueNew.put(new BeanReference(null), new BeanReference(null));realValue originValueNew;} else {realValue originalValue;}}return realValue;}private String getBeanName(String simpleName) {if (simpleName null) {throw new IllegalArgumentException(simpleName不能为空);}String firstChar simpleName.charAt(0) ;return firstChar.toLowerCase() simpleName.substring(1);}private Constructor? determineConstructor(BeanDefinition bd, Object[] args) throws Exception {/*判定构造方法的逻辑应是怎样的1 先根据参数的类型进行精确匹配查找如未找到则进行第2步查找2获得所有的构造方法遍历通过参数数量过滤再比对形参类型与实参类型。* */Constructor? ct null;//没有参数则用无参构造方法if (args null) {return bd.getBeanClass().getConstructor(null);}// 对于原型bean,从第二次开始获取bean实例时可直接获得第一次缓存的构造方法。ct bd.getConstructor();if (ct ! null) {return ct;}// 1 根据参数类型获取精确匹配的构造方法Class?[] paramTypes new Class[args.length];int j 0;for (Object p : args) {paramTypes[j] p.getClass();}try {ct bd.getBeanClass().getConstructor(paramTypes);} catch (Exception e) {// 这个异常不需要处理}if (ct null) {// 2 没有精确参数类型匹配的获得所有的构造方法遍历通过参数数量过滤再比对形参类型与实参类型。// 判断逻辑先判断参数数量再依次比对形参类型与实参类型outer:for (Constructor? ct0 : bd.getBeanClass().getConstructors()) {Class?[] paramterTypes ct0.getParameterTypes();if (paramterTypes.length args.length) { //通过参数数量过滤for (int i 0; i paramterTypes.length; i) { //再依次比对形参类型与实参类型是否匹配if (!paramterTypes[i].isAssignableFrom(args[i].getClass())) {continue outer; //参数类型不可赋值不匹配跳到外层循环继续下一个}}ct ct0; //匹配上了break outer;}}}if (ct ! null) {// 对于原型bean,可以缓存找到的构造方法方便下次构造实例对象。在BeanDefinfition中获取设置所用构造方法的方法。// 同时在上面增加从beanDefinition中获取的逻辑。if (bd.isPrototype()) {bd.setConstructor(ct);}return ct;} else {throw new Exception(不存在对应的构造方法 bd);}}private Method determineFactoryMethod(BeanDefinition bd, Object[] args, Class? type) throws Exception {/*判定工厂方法的逻辑同构造方法的判定逻辑1 先根据实参的类型进行精确匹配查找如未找到则进行第2步查找2 获得所有方法遍历通过方法名、参数数量过滤再比对形参类型与实参类型。* */String methodName bd.getFactoryMethodName();if (args null) {return type.getMethod(methodName, null);}Method m null;// 对于原型bean,从第二次开始获取bean实例时可直接获得第一次缓存的构造方法。m bd.getFactoryMethod();if (m ! null) {return m;}// 1 先根据实参的类型进行精确匹配查找Class[] paramTypes new Class[args.length];int j 0;for (Object p : args) {paramTypes[j] p.getClass();}try {m type.getMethod(methodName, paramTypes);} catch (Exception e) {// 这个异常不需要处理}if (m null) {// 没有精确参数类型匹配的则遍历匹配所有的方法// 2 获得所有方法遍历通过方法名、参数数量过滤再比对形参类型与实参类型。outer:for (Method m0 : type.getMethods()) {if (!m0.getName().equals(methodName)) {continue;}Class?[] paramterTypes m.getParameterTypes();if (paramterTypes.length args.length) {for (int i 0; i paramterTypes.length; i) {if (!paramterTypes[i].isAssignableFrom(args[i].getClass())) {continue outer;}}m m0;break outer;}}}if (m ! null) {// 对于原型bean,可以缓存找到的方法方便下次构造实例对象。在BeanDefinfition中获取设置所用方法的方法。// 同时在上面增加从beanDefinition中获取的逻辑。if (bd.isPrototype()) {bd.setFactoryMethod(m);}return m;} else {throw new Exception(不存在对应的构造方法 bd);}}// 静态工厂方法private Object createInstanceByStaticFactoryMethod(BeanDefinition bd) throws Exception {Object[] realArgs this.getConstructorArgumentValues(bd);Class? type bd.getBeanClass();Method m this.determineFactoryMethod(bd, realArgs, type);return m.invoke(type, realArgs);}// 工厂bean方式来构造对象private Object createInstanceByFactoryBean(BeanDefinition bd) throws Exception {Object[] realArgs this.getConstructorArgumentValues(bd);Method m this.determineFactoryMethod(bd, realArgs, this.getType(bd.getFactoryBeanName()));Object factoryBean this.doGetBean(bd.getFactoryBeanName());return m.invoke(factoryBean, realArgs);}/*** 执行初始化方法** param beanDefinition bean定义* param instance 实例对象* throws Exception 异常*/private void doInit(BeanDefinition beanDefinition, Object instance) throws Exception {// 执行初始化方法if (StringUtils.isNotBlank(beanDefinition.getInitMethodName())) {Method m instance.getClass().getMethod(beanDefinition.getInitMethodName(), null);m.invoke(instance, null);}}Overridepublic void close() throws IOException {// 执行单例实例的销毁方法for (EntryString, BeanDefinition e : this.beanDefintionMap.entrySet()) {String beanName e.getKey();BeanDefinition bd e.getValue();if (bd.isSingleton() StringUtils.isNotBlank(bd.getDestroyMethodName())) {Object instance this.singletonBeanMap.get(beanName);try {Method m instance.getClass().getMethod(bd.getDestroyMethodName(), null);m.invoke(instance, null);} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException| InvocationTargetException e1) {log.error(执行bean[ beanName ] bd 的 销毁方法异常, e1);}}}} }我们通过构造方法创建其实是通过无参构造方法来处理的这时我们需要改变这块的逻辑通过有参构造方法来实现。 // 构造方法来构造对象 private Object createInstanceByConstructor(BeanDefinition bd)throws InstantiationException, IllegalAccessException {try {return bd.getBeanClass().newInstance();} catch (SecurityException e1) {log.error(创建bean的实例异常,beanDefinition bd, e1);throw e1;} }我们就需要对上面的方法做出改变。 // 构造方法来构造对象 private Object createInstanceByConstructor(BeanDefinition bd)throws InstantiationException, IllegalAccessException {// 1. 得到真正的参数值List? constructorArgumentValues bd.getConstructorArgumentValues(); // 2.根据对应的构造参数依赖获取到对应的 Constructor Constructor constructor 得到对应的构造方法// 3.用实际参数值调用构造方法创建对应的对象return constructor.newInstance(Object ... 实参值); }通过上面的分析我们需要获取对应的构造器。这块我们需要通过反射来获取了。下面是具体的实现逻辑 根据上面的分析实现逻辑可分为两步 先根据参数的类型进行精确匹配查找如果没有找到继续执行第二步操作获得所有的构造方法遍历构造方法通过参数数量过滤再比对形参与实参的类型 因为这里有个情况实参是Boy构造方法的形参是Person第一种精确匹配就没有办法关联了。 具体的实现代码如下 private Constructor? determineConstructor(BeanDefinition bd, Object[] args) throws Exception {/*判定构造方法的逻辑应是怎样的1 先根据参数的类型进行精确匹配查找如未找到则进行第2步查找2获得所有的构造方法遍历通过参数数量过滤再比对形参类型与实参类型。* */Constructor? ct null;//没有参数则用无参构造方法if (args null) {return bd.getBeanClass().getConstructor(null);}// 1 先根据参数的类型进行精确匹配查找Class?[] paramTypes new Class[args.length];int j 0;for (Object p : args) {paramTypes[j] p.getClass();}try {ct bd.getBeanClass().getConstructor(paramTypes);} catch (Exception e) {// 这个异常不需要处理}if (ct null) {// 2 没有精确参数类型匹配的获得所有的构造方法遍历通过参数数量过滤再比对形参类型与实参类型。// 判断逻辑先判断参数数量再依次比对形参类型与实参类型outer:for (Constructor? ct0 : bd.getBeanClass().getConstructors()) {Class?[] paramterTypes ct0.getParameterTypes();if (paramterTypes.length args.length) { //通过参数数量过滤for (int i 0; i paramterTypes.length; i) { //再依次比对形参类型与实参类型是否匹配if (!paramterTypes[i].isAssignableFrom(args[i].getClass())) {continue outer; //参数类型不可赋值不匹配跳到外层循环继续下一个}}ct ct0; //匹配上了break outer;}}}if (ct ! null) {return ct;} else {throw new Exception(不存在对应的构造方法 bd);} }上面我们考虑的是BeanFactory通过构造器来获取对象的逻辑那如果我们是通过静态工厂方法或者成员工厂方法的方式来处理的那么构造参数依赖的处理是否和前面的是一样的呢其实是差不多的我们需要根据对应的构造参数来推断对应的工厂方法 // 静态工厂方法 private Object createInstanceByStaticFactoryMethod(BeanDefinition bd) throws Exception {Object[] realArgs this.getConstructorArgumentValues(bd);Class? type bd.getBeanClass();Method m this.determineFactoryMethod(bd, realArgs, type);return m.invoke(type, realArgs); }// 工厂bean方式来构造对象 private Object createInstanceByFactoryBean(BeanDefinition bd) throws Exception {Object[] realArgs this.getConstructorArgumentValues(bd);Method m this.determineFactoryMethod(bd, realArgs, this.getType(bd.getFactoryBeanName()));Object factoryBean this.doGetBean(bd.getFactoryBeanName());return m.invoke(factoryBean, realArgs); }5.缓存功能 对于上面的处理过程相信大家应该清楚了我们通过推断也得到了对应的构造方法或者对应的工厂方法那么我们可以不可以在下次需要再次获取的时候省略掉推导的过程呢显然我们可以在BeanDefinition中增加缓存方法可以实现这个需求。 6. 循环依赖问题 上图是循环依赖的三种情况虽然方式有点不一样但是循环依赖的本质是一样的就你的完整创建要依赖于我我的完整创建也依赖于你。相互依赖从而没法完整创建造成失败。 我们通过构造参数依赖是完全可能出现上面的情况的那么这种情况我们能解决吗构造依赖的情况我们是解决不了的。 public class Test01 {public static void main(String[] args) {new TestService1();} }class TestService1{private TestService2 testService2 new TestService2(); }class TestService2{private TestService1 testService1 new TestService1(); }既然解决不了那么我们在程序中如果出现了应该要怎么来解决呢 其实我们可以在创建一个Bean的时候记录下这个Bean当这个Bean创建完成后我们再移除这个Bean然后我们在getBean的时候判断记录中是否有该Bean如果有就判断为循环依赖并抛出异常。数据结构我们可以通过Set集合来处理。 到此构造注入的实现就告一段落了。 三、属性注入 上面搞定了构造注入的方式。接下来我们再看看属性注入的方式有什么需要注意的地方。 1. 属性依赖分析 属性依赖就是某个属性依赖某个值。 public class Girl {private String name;private int age;private ListClothes ClothesList;// .... }那么在获取实例对象后如何根据相关的配置来给对应的属性来赋值呢这时我们可以定义一个实体类 PropertyValue来记录相关的属性和值。 2.BeanDefinition实现 这时我们就需要在BeanDefinition中关联相关属性信息了。 3.BeanFactory实现 然后我们在BeanFactory的默认实现DefaultBeanFactory中实现属性值的依赖注入。 // 创建好实例对象 // 给属性依赖赋值 this.setPropertyDIValues(bd,instance); // 执行初始化相关方法 this.doInit(bd,instance);具体的实现代码如下 // 给入属性依赖 private void setPropertyDIValues(BeanDefinition bd, Object instance) throws Exception {if (CollectionUtils.isEmpty(bd.getPropertyValues())) {return;}for (PropertyValue pv : bd.getPropertyValues()) {if (StringUtils.isBlank(pv.getName())) {continue;}Class? clazz instance.getClass();Field p clazz.getDeclaredField(pv.getName());//暴力访问 privatep.setAccessible(true);p.set(instance, this.getOneArgumentRealValue(pv.getValue()));} }4.循环依赖问题 在构造参数依赖中我们发现没有办法解决在属性依赖中同样会存在循环依赖的问题这时我们能解决吗 其实这种循环依赖的情况不在IOC场景下非常好解决。如下 Boy b new Boy(); Girl g new Girl(); b.setGirl(g); g.setBoy(b);但是在IOC好像不是太好解决 针对这种情况我们需要通过 提前暴露来解决这个问题具体看代码!!! private void doEarlyExposeBuildingBeans(String beanName, Object instance) {MapString,Object earlyExposeBuildingBeansMap earlyExposeBuildingBeans.get();if(earlyExposeBuildingBeansMap null) {earlyExposeBuildingBeansMap new HashMap();earlyExposeBuildingBeans.set(earlyExposeBuildingBeansMap);}earlyExposeBuildingBeansMap.put(beanName,instance); }最后现阶段已经实现的类图结构
文章转载自:
http://www.morning.hnrpk.cn.gov.cn.hnrpk.cn
http://www.morning.qscsy.cn.gov.cn.qscsy.cn
http://www.morning.kbqws.cn.gov.cn.kbqws.cn
http://www.morning.ccphj.cn.gov.cn.ccphj.cn
http://www.morning.fpqsd.cn.gov.cn.fpqsd.cn
http://www.morning.hkgcx.cn.gov.cn.hkgcx.cn
http://www.morning.cpwmj.cn.gov.cn.cpwmj.cn
http://www.morning.jhxdj.cn.gov.cn.jhxdj.cn
http://www.morning.webife.com.gov.cn.webife.com
http://www.morning.qyqmj.cn.gov.cn.qyqmj.cn
http://www.morning.pxsn.cn.gov.cn.pxsn.cn
http://www.morning.fwzjs.cn.gov.cn.fwzjs.cn
http://www.morning.pjtw.cn.gov.cn.pjtw.cn
http://www.morning.wcczg.cn.gov.cn.wcczg.cn
http://www.morning.rnqrl.cn.gov.cn.rnqrl.cn
http://www.morning.lqjpb.cn.gov.cn.lqjpb.cn
http://www.morning.jfjqs.cn.gov.cn.jfjqs.cn
http://www.morning.mfmx.cn.gov.cn.mfmx.cn
http://www.morning.rmtxp.cn.gov.cn.rmtxp.cn
http://www.morning.yltnl.cn.gov.cn.yltnl.cn
http://www.morning.qzpsk.cn.gov.cn.qzpsk.cn
http://www.morning.ppghc.cn.gov.cn.ppghc.cn
http://www.morning.bmzxp.cn.gov.cn.bmzxp.cn
http://www.morning.pljxz.cn.gov.cn.pljxz.cn
http://www.morning.zxhpx.cn.gov.cn.zxhpx.cn
http://www.morning.gqfbl.cn.gov.cn.gqfbl.cn
http://www.morning.sjwiki.com.gov.cn.sjwiki.com
http://www.morning.gnhsg.cn.gov.cn.gnhsg.cn
http://www.morning.byjwl.cn.gov.cn.byjwl.cn
http://www.morning.rwfj.cn.gov.cn.rwfj.cn
http://www.morning.nlryq.cn.gov.cn.nlryq.cn
http://www.morning.xptkl.cn.gov.cn.xptkl.cn
http://www.morning.zglrl.cn.gov.cn.zglrl.cn
http://www.morning.sxygc.cn.gov.cn.sxygc.cn
http://www.morning.fnlnp.cn.gov.cn.fnlnp.cn
http://www.morning.rmppf.cn.gov.cn.rmppf.cn
http://www.morning.dmsxd.cn.gov.cn.dmsxd.cn
http://www.morning.qpnb.cn.gov.cn.qpnb.cn
http://www.morning.bkslb.cn.gov.cn.bkslb.cn
http://www.morning.qmpbs.cn.gov.cn.qmpbs.cn
http://www.morning.tthmg.cn.gov.cn.tthmg.cn
http://www.morning.hsdhr.cn.gov.cn.hsdhr.cn
http://www.morning.bbxbh.cn.gov.cn.bbxbh.cn
http://www.morning.zbjfq.cn.gov.cn.zbjfq.cn
http://www.morning.krhkn.cn.gov.cn.krhkn.cn
http://www.morning.kzslk.cn.gov.cn.kzslk.cn
http://www.morning.gwjnm.cn.gov.cn.gwjnm.cn
http://www.morning.tturfsoc.com.gov.cn.tturfsoc.com
http://www.morning.bmjfp.cn.gov.cn.bmjfp.cn
http://www.morning.htbgz.cn.gov.cn.htbgz.cn
http://www.morning.cjqcx.cn.gov.cn.cjqcx.cn
http://www.morning.wnjbn.cn.gov.cn.wnjbn.cn
http://www.morning.lcxdm.cn.gov.cn.lcxdm.cn
http://www.morning.rfhwc.cn.gov.cn.rfhwc.cn
http://www.morning.lsfzq.cn.gov.cn.lsfzq.cn
http://www.morning.kjgrg.cn.gov.cn.kjgrg.cn
http://www.morning.mzmqg.cn.gov.cn.mzmqg.cn
http://www.morning.jopebe.cn.gov.cn.jopebe.cn
http://www.morning.tzpqc.cn.gov.cn.tzpqc.cn
http://www.morning.ndmh.cn.gov.cn.ndmh.cn
http://www.morning.smqjl.cn.gov.cn.smqjl.cn
http://www.morning.sjjq.cn.gov.cn.sjjq.cn
http://www.morning.mfrb.cn.gov.cn.mfrb.cn
http://www.morning.lndongguan.com.gov.cn.lndongguan.com
http://www.morning.slkqd.cn.gov.cn.slkqd.cn
http://www.morning.ndpzm.cn.gov.cn.ndpzm.cn
http://www.morning.bpkqd.cn.gov.cn.bpkqd.cn
http://www.morning.jzlkq.cn.gov.cn.jzlkq.cn
http://www.morning.lylkh.cn.gov.cn.lylkh.cn
http://www.morning.gkgr.cn.gov.cn.gkgr.cn
http://www.morning.dktyc.cn.gov.cn.dktyc.cn
http://www.morning.psxcr.cn.gov.cn.psxcr.cn
http://www.morning.dpmkn.cn.gov.cn.dpmkn.cn
http://www.morning.ysllp.cn.gov.cn.ysllp.cn
http://www.morning.csgwd.cn.gov.cn.csgwd.cn
http://www.morning.ljhnn.cn.gov.cn.ljhnn.cn
http://www.morning.dwztj.cn.gov.cn.dwztj.cn
http://www.morning.fjshyc.com.gov.cn.fjshyc.com
http://www.morning.bsbcp.cn.gov.cn.bsbcp.cn
http://www.morning.gqflj.cn.gov.cn.gqflj.cn
http://www.tj-hxxt.cn/news/271728.html

相关文章:

  • 站长之家域名哪些网站是做免费推广的
  • 班级建设网站首页山东省住房城乡建设厅官网
  • 多站点网站群的建设与管理系统给wordpress博客加上一个娃娃
  • 西安 网站建设 培训班专业模板网站制作多少钱
  • 国内外免费域名解析网站网站移动端是什么问题
  • 网上做网站广告投放做哪个app软件下载
  • 怎样在局域网做网站成都网站营销seo多少费用
  • 如何做网站充值广州网站建设支付
  • seo网站优化培训怎么做wordpress设置不显示摘要
  • 合肥专业建站南昌网站建设怎么样
  • 如何提高网站在搜索引擎中的排名网站标签怎么做跳转页面
  • 郑州网站高端设计品牌网站定制
  • 佛山外贸网站建设渠道哈尔滨网站开发电话
  • 呼家楼做网站的公司建设网站怎么入账
  • 北流网站建设杭州10大软件开发公司
  • 北京做网站哪个好wordpress开启缓存
  • 做网站推广前途个人网站开发技术
  • 岱山县网站建设wordpress singular
  • WordPress一键开启全站SSL.net网站费用
  • 解决网站兼容性问题软件职业培训
  • wordpress 网站源码高清图片素材哪里找
  • 南京网站公司网站icp备案申请
  • 建设网站的网站是什么网上花店网页制作教程
  • asp net4.0网站开发网站建设需要什么研究条件
  • 淄川网站建设自建网站注册域名很有必要
  • 丹东新区建设发展集团网站做个手机网站有必要吗
  • 网站流量转化免费提供网站
  • 网站建设报价东莞购物网站推广方案
  • 陆家网站建设手机网站制作与建设
  • 帝国cms网站地址移动网站建设初学视频教程