BeanDefinition
package com.lv.spring.bean;
import org.springframework.util.StringUtils;
import java.util.List;
/**
* Created by lvyanghui
* 2018/11/28 9:35
*/
public interface BeanDefinition {
String SCOPE_SINGLETON = "singleton";
String SCOPE_PROTOTYPE = "prototype";
Class<?> getBeanClass();
String getScope();
boolean isSingleton();
boolean isPrototype();
String getFactoryBeanName();
String getFactoryMethodName();
String getInitMethodName();
String getDestroyMethodName();
List<PropertyValue> getConstructorValues();
List<PropertyValue> getPropertyValues();
default boolean validate(){
if(this.getBeanClass() == null){
if(StringUtils.isEmpty(this.getFactoryBeanName()) || StringUtils.isEmpty(this.getFactoryMethodName())){
return false;
}
}else{
if(!StringUtils.isEmpty(this.getFactoryBeanName())){
return false;
}
}
return true;
}
}
BeanDefinitionRegistry
package com.lv.spring.bean;
/**
* Created by lvyanghui
* 2018/12/19 14:23
*/
public interface BeanDefinitionRegistry {
void registerBeanDefinition(String beanName,BeanDefinition beanDefinition)throws BeanDefinitionRegistryException;
BeanDefinition getBeanDefinition(String beanName);
boolean containsBeanDefinition(String beanName);
}
BeanDefinitionRegistryException
package com.lv.spring.bean;
/**
* Created by lvyanghui
* 2018/12/20 11:07
*/
public class BeanDefinitionRegistryException extends Exception{
public BeanDefinitionRegistryException(){
super();
}
public BeanDefinitionRegistryException(Throwable cause){
super(cause);
}
public BeanDefinitionRegistryException(String message){
super(message);
}
public BeanDefinitionRegistryException(String message,Throwable cause){
super(message,cause);
}
}
BeanFactory
package com.lv.spring.bean;
/**
* Created by lvyanghui
* 2018/12/19 14:21
*/
public interface BeanFactory {
Object getBean(String beanName) throws Exception;
}
BeanRefernerce
package com.lv.spring.bean;
/**
* Created by lvyanghui
* 2018/12/21 10:10
*/
public class BeanRefernerce {
private String name;
public BeanRefernerce(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
DefaultBeanFactory
package com.lv.spring.bean;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
/**
* Created by lvyanghui
* 2018/12/19 14:50
*/
public class DefaultBeanFactory implements BeanFactory,BeanDefinitionRegistry,Closeable {
private Map<String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
private Map<String,Object> beanMap = new ConcurrentHashMap<String,Object>(256);
@Override
public void registerBeanDefinition(String beanName,BeanDefinition beanDefinition) throws BeanDefinitionRegistryException{
Objects.requireNonNull(beanName,"beanName不能为空!");
Objects.requireNonNull(beanDefinition,"beanDefinition不能为空!");
if(!beanDefinition.validate()){
throw new BeanDefinitionRegistryException("验证beanDefinition参数不合法");
}
if(beanDefinitionMap.containsKey(beanName)){
throw new BeanDefinitionRegistryException("已经存在beanDefinition");
}
beanDefinitionMap.put(beanName,beanDefinition);
}
@Override
public BeanDefinition getBeanDefinition(String beanName) {
return beanDefinitionMap.get(beanName);
}
@Override
public boolean containsBeanDefinition(String beanName) {
return beanDefinitionMap.containsKey(beanName);
}
@Override
public Object getBean(String beanName) throws Exception{
return doGetBean(beanName);
}
public Object doGetBean(String beanName) throws Exception {
Objects.requireNonNull(beanName,"beanName不能为空");
Object instance = beanMap.get(beanName);
if(null != instance){
return instance;
}
BeanDefinition beanDefinition = getBeanDefinition(beanName);
Objects.requireNonNull(beanDefinition, "beanDefinition不能为空");
Class<?> classType = beanDefinition.getBeanClass();
if(classType != null){
if(beanDefinition.getFactoryMethodName() == null){
instance = createInstanceByConstructor(beanDefinition);
}else{
instance = createInstanceByStaticFactoryMethod(beanDefinition);
}
}else{
instance = createInstanceByFactoryMethod(beanDefinition);
}
doInitMethod(beanDefinition,instance);
if(beanDefinition.isSingleton()){
beanMap.put(beanName,instance);
}
return instance;
}
public Object createInstanceByConstructor(BeanDefinition beanDefinition)throws Exception{
Class<?> classType = beanDefinition.getBeanClass();
Object[] args = getRealValues(beanDefinition.getConstructorValues());
if(null == args){
return classType.newInstance();
}else{
Constructor constructor = determinConstructor(beanDefinition,args);
if(null == constructor){
return classType.newInstance();
}else{
return constructor.newInstance(args);
}
}
}
public Object createInstanceByStaticFactoryMethod(BeanDefinition beanDefinition)throws Exception{
Class<?> classType = beanDefinition.getBeanClass();
Object[] args = getRealValues(beanDefinition.getConstructorValues());
Method method = determinMethod(beanDefinition,args,classType);
return method.invoke(classType,args);
}
public Object createInstanceByFactoryMethod(BeanDefinition beanDefinition)throws Exception{
Object factoryBean = doGetBean(beanDefinition.getFactoryBeanName());
Object[] args = getRealValues(beanDefinition.getConstructorValues());
Method method = determinMethod(beanDefinition, args,factoryBean.getClass());
return method.invoke(factoryBean,args);
}
public void doInitMethod(BeanDefinition beanDefinition,Object instance) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
String initMethod = beanDefinition.getInitMethodName();
if(!StringUtils.isEmpty(initMethod)){
Method method = instance.getClass().getMethod(initMethod, null);
method.invoke(instance,null);
}
}
public Constructor<?> determinConstructor(BeanDefinition beanDefinition,Object[] args)throws Exception{
Constructor<?>[] constructors = beanDefinition.getBeanClass().getConstructors();
outer: for(Constructor constructor : constructors){
Class[] parameterTypes = constructor.getParameterTypes();
int i = 0;
if(parameterTypes.length == args.length){
for(Object arg : args){
if(!parameterTypes[i++].isAssignableFrom(arg.getClass())){
continue outer;
}
if(i == args.length){
return constructor;
}
}
}
}
return null;
}
public Method determinMethod(BeanDefinition beanDefinition,Object[] args,Class<?> classType)throws Exception{
Method method = null;
if(null == args){
method = classType.getMethod(beanDefinition.getFactoryMethodName());
}
Method[] methods = classType.getMethods();
outer: for(Method me : methods){
if(!me.getName().equals(beanDefinition.getFactoryMethodName())){
continue ;
}else{
Class<?>[] parameterTypes = me.getParameterTypes();
int i = 0;
if(args.length == parameterTypes.length){
for(Object arg : args){
if(!parameterTypes[i++].isAssignableFrom(arg.getClass())){
continue outer;
}
if(i == args.length){
return me;
}
}
}
}
}
if(null == method){
throw new Exception("找不到方法");
}
return method;
}
public Object[] getRealValues(List<PropertyValue> propertyValues)throws Exception{
Object[] realValues = null;
if(!CollectionUtils.isEmpty(propertyValues)){
List<PropertyValue> resolvedPropertyValues = resolvePropertyValues(propertyValues);
realValues = new Object[resolvedPropertyValues.size()];
for(int i = 0,len = resolvedPropertyValues.size(); i < len; i++){
realValues[i] = resolvedPropertyValues.get(i).getValue();
}
}
return realValues;
}
public List<PropertyValue> resolvePropertyValues(List<PropertyValue> propertyValues)throws Exception{
List<PropertyValue> resolvedPropertyValues = new ArrayList<>();
Object value = null;
for(PropertyValue propertyValue : propertyValues){
value = propertyValue.getValue();
if(value instanceof BeanRefernerce){
propertyValue.setValue(getBean(((BeanRefernerce) value).getName()));
}else if(value instanceof String){
propertyValue.setValue(String.valueOf(value));
}else if(value instanceof Integer){
}else if(value instanceof List){
} else if(value instanceof Map){
}
resolvedPropertyValues.add(propertyValue);
}
return resolvedPropertyValues;
}
@Override
public void close() throws IOException {
//执行单例实例的销毁方法
for(Map.Entry<String,BeanDefinition> entry : beanDefinitionMap.entrySet()){
String beanName = entry.getKey();
BeanDefinition beanDefinition = entry.getValue();
if(beanDefinition.isSingleton() && !StringUtils.isEmpty(beanDefinition.getDestroyMethodName())){
Object instance = beanMap.get(beanName);
try {
Method method = instance.getClass().getMethod(beanDefinition.getDestroyMethodName(),null);
method.invoke(instance,null);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
}
}
}
}
GenericBeanDefinition
package com.lv.spring.bean;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* Created by lvyanghui
* 2018/12/19 14:42
*/
public class GenericBeanDefinition implements BeanDefinition{
private Class<?> beanClass;
private String scope=SCOPE_SINGLETON;
private String factoryBeanName;
private String factoryMethodName;
private String initMethodName;
private String destroyMethodName;
private List<PropertyValue> constructorValues = new ArrayList<>();
private List<PropertyValue> propertyValues = new ArrayList<>();
public void setBeanClass(Class<?> beanClass) {
this.beanClass = beanClass;
}
public void setScope(String scope) {
if(!StringUtils.isEmpty(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;
}
public void setConstructorValues(List<PropertyValue> constructorValues) {
this.constructorValues = constructorValues;
}
public void setPropertyValues(List<PropertyValue> propertyValues) {
this.propertyValues = propertyValues;
}
@Override
public Class<?> getBeanClass() {
return beanClass;
}
@Override
public String getScope() {
return scope;
}
@Override
public boolean isSingleton() {
return SCOPE_SINGLETON.equals(scope);
}
@Override
public boolean isPrototype() {
return SCOPE_PROTOTYPE.equals(scope);
}
@Override
public String getFactoryBeanName() {
return factoryBeanName;
}
@Override
public String getFactoryMethodName() {
return factoryMethodName;
}
@Override
public String getInitMethodName() {
return initMethodName;
}
@Override
public String getDestroyMethodName() {
return destroyMethodName;
}
@Override
public List<PropertyValue> getConstructorValues() {
return constructorValues;
}
@Override
public List<PropertyValue> getPropertyValues() {
return propertyValues;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GenericBeanDefinition that = (GenericBeanDefinition) o;
if (!beanClass.equals(that.beanClass)) return false;
if (!destroyMethodName.equals(that.destroyMethodName)) return false;
if (!factoryBeanName.equals(that.factoryBeanName)) return false;
if (!factoryMethodName.equals(that.factoryMethodName)) return false;
if (!initMethodName.equals(that.initMethodName)) return false;
if (!scope.equals(that.scope)) return false;
return true;
}
@Override
public int hashCode() {
int result = beanClass.hashCode();
result = 31 * result + scope.hashCode();
result = 31 * result + factoryBeanName.hashCode();
result = 31 * result + factoryMethodName.hashCode();
result = 31 * result + initMethodName.hashCode();
result = 31 * result + destroyMethodName.hashCode();
return result;
}
}
PropertyValue
package com.lv.spring.bean;
/**
* Created by lvyanghui
* 2018/12/21 9:47
*/
public class PropertyValue {
private String name;
private Object value;
public PropertyValue(String name, Object value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
ABean
package com.lv.spring.test;
/**
* Created by lvyanghui
* 2018/12/19 16:44
*/
public class ABean {
public void initMethod(){
System.out.println("ABean 执行初始化方法.....");
}
public void methodA(){
System.out.println("ABean 执行methodA.......");
}
public void destoryA(){
System.out.println("ABean 执行destoryA.......");
}
}
ABeanFactory
package com.lv.spring.test;
/**
* Created by lvyanghui
* 2018/12/19 16:44
*/
public class ABeanFactory {
public static ABean getBeanByFactory(){
return new ABean();
}
public ABean getBeanByFactoryBean(){
return new ABean();
}
}
BBean
package com.lv.spring.test;
/**
* Created by lvyanghui
* 2018/12/19 16:44
*/
public class BBean {
private String name;
private ABean aBean;
public BBean() {
}
public BBean(String name) {
this.name = name;
}
public BBean(String name, ABean aBean) {
this.name = name;
this.aBean = aBean;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ABean getaBean() {
return aBean;
}
public void setaBean(ABean aBean) {
this.aBean = aBean;
}
}
BBeanFactory
package com.lv.spring.test;
/**
* Created by lvyanghui
* 2018/12/19 16:44
*/
public class BBeanFactory {
public static BBean getBeanByFactory(String name, ABean aBean){
return new BBean();
}
public BBean getBeanByFactoryBean(String name, ABean aBean,String kk){
return new BBean();
}
}
BeanFactoryDITest
package com.lv;
import com.lv.spring.bean.BeanRefernerce;
import com.lv.spring.bean.DefaultBeanFactory;
import com.lv.spring.bean.GenericBeanDefinition;
import com.lv.spring.bean.PropertyValue;
import com.lv.spring.test.ABean;
import com.lv.spring.test.BBean;
import com.lv.spring.test.BBeanFactory;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
/**
* Created by lvyanghui
* 2018/12/19 16:46
*/
public class BeanFactoryDITest {
static DefaultBeanFactory beanFactory = new DefaultBeanFactory();
@Test
public void registerConstructorDI()throws Exception{
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setBeanClass(ABean.class);
beanFactory.registerBeanDefinition("aa", bd);
bd = new GenericBeanDefinition();
bd.setBeanClass(BBean.class);
PropertyValue property1 = new PropertyValue("name","lvyanghui");
BeanRefernerce beanRefernerce = new BeanRefernerce("aa");
PropertyValue property2 = new PropertyValue("ref",beanRefernerce);
PropertyValue property3 = new PropertyValue("kkk","ssdfsdf");
List<PropertyValue> propertyValues = new ArrayList<>();
propertyValues.add(property1);
propertyValues.add(property2);
propertyValues.add(property3);
bd.setConstructorValues(propertyValues);
beanFactory.registerBeanDefinition("bb",bd);
BBean bBean = (BBean)beanFactory.getBean("bb");
System.out.println(bBean);
}
@Test
public void registerStaticFactoryMethod()throws Exception{
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setBeanClass(ABean.class);
beanFactory.registerBeanDefinition("aa", bd);
bd = new GenericBeanDefinition();
bd.setBeanClass(BBeanFactory.class);
bd.setFactoryMethodName("getBeanByFactory");
PropertyValue property1 = new PropertyValue("name","lvyanghui");
BeanRefernerce beanRefernerce = new BeanRefernerce("aa");
PropertyValue property2 = new PropertyValue("ref",beanRefernerce);
//PropertyValue property3 = new PropertyValue("kkk","ssdfsdf");
List<PropertyValue> propertyValues = new ArrayList<>();
propertyValues.add(property1);
propertyValues.add(property2);
//propertyValues.add(property3);
bd.setConstructorValues(propertyValues);
beanFactory.registerBeanDefinition("factoryMethod",bd);
BBean bBean = (BBean)beanFactory.getBean("factoryMethod");
System.out.println(bBean);
}
@Test
public void registerFactoryMethod()throws Exception{
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setBeanClass(ABean.class);
beanFactory.registerBeanDefinition("aa", bd);
bd = new GenericBeanDefinition();
bd.setBeanClass(BBeanFactory.class);
String fbname = "factory";
beanFactory.registerBeanDefinition(fbname, bd);
bd = new GenericBeanDefinition();
bd.setFactoryBeanName(fbname);
bd.setFactoryMethodName("getBeanByFactoryBean");
PropertyValue property1 = new PropertyValue("name","lvyanghui");
BeanRefernerce beanRefernerce = new BeanRefernerce("aa");
PropertyValue property2 = new PropertyValue("ref",beanRefernerce);
PropertyValue property3 = new PropertyValue("kk","ssdfsdf");
List<PropertyValue> propertyValues = new ArrayList<>();
propertyValues.add(property1);
propertyValues.add(property2);
propertyValues.add(property3);
bd.setConstructorValues(propertyValues);
beanFactory.registerBeanDefinition("factoryBean",bd);
BBean bBean = (BBean)beanFactory.getBean("factoryBean");
System.out.println(bBean);
}
}
BeanFactoryTest
package com.lv;
import com.lv.spring.bean.BeanDefinitionRegistryException;
import com.lv.spring.bean.DefaultBeanFactory;
import com.lv.spring.bean.GenericBeanDefinition;
import com.lv.spring.test.ABean;
import com.lv.spring.test.ABeanFactory;
import org.junit.AfterClass;
import org.junit.Test;
/**
* Created by lvyanghui
* 2018/12/19 16:46
*/
public class BeanFactoryTest {
static DefaultBeanFactory beanFactory = new DefaultBeanFactory();
@Test
public void register()throws BeanDefinitionRegistryException{
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setBeanClass(ABean.class);
//bd.setScope("singleton");
//bd.setScope("prototype");
bd.setInitMethodName("initMethod");
beanFactory.registerBeanDefinition("aa", bd);
}
@Test
public void registerStaticFactoryMethod()throws BeanDefinitionRegistryException{
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setBeanClass(ABeanFactory.class);
bd.setFactoryMethodName("getBeanByFactory");
beanFactory.registerBeanDefinition("bb", bd);
}
@Test
public void registerFactoryMethod()throws BeanDefinitionRegistryException{
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setBeanClass(ABeanFactory.class);
String fbname = "factory";
beanFactory.registerBeanDefinition(fbname, bd);
bd = new GenericBeanDefinition();
bd.setFactoryBeanName(fbname);
bd.setFactoryMethodName("getBeanByFactoryBean");
beanFactory.registerBeanDefinition("factoryBean",bd);
}
@AfterClass
public static void testFactory()throws Exception{
System.out.println("spring 构造方式------------");
for (int i = 0; i < 3; i++) {
ABean abean = (ABean)beanFactory.getBean("aa");
System.out.println(abean);
}
System.out.println("spring 静态工厂方式------------");
for (int i = 0; i < 3; i++) {
ABean abean = (ABean)beanFactory.getBean("bb");
System.out.println(abean);
}
System.out.println("spring 工厂方法方式------------");
for (int i = 0; i < 3; i++) {
ABean abean = (ABean)beanFactory.getBean("factoryBean");
System.out.println(abean);
}
}
}