/**
* Copyright (c) 2016, biezhi 王爵 (biezhi.me@gmail.com)
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.blade.ioc;
import com.blade.ioc.loader.IocLoader;
import com.blade.kit.Assert;
import com.blade.kit.IocKit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Modifier;
import java.util.*;
/**
* The default IOC container implementation
*
* @author <a href="mailto:biezhi.me@gmail.com" target="_blank">biezhi</a>
* @since 1.5
*/
public class SimpleIoc implements Ioc {
private static final Logger LOGGER = LoggerFactory.getLogger(Ioc.class);
private final Map<String, BeanDefine> pool = new HashMap<>(32);
/**
* ioc loader
*/
@Override
public void load(IocLoader loader) {
loader.load(this);
}
/**
* Add user-defined objects
*/
@Override
public void addBean(Object bean) {
Assert.notNull(bean);
addBean(bean.getClass().getName(), bean);
}
/**
* Add user-defined objects
*/
public void addBean(Class<?> beanClass, Object bean) {
Assert.notNull(beanClass);
addBean(beanClass.getName(), bean);
}
/**
* Add user-defined objects
*/
public void addBean(String name, Object bean) {
Assert.notNull(bean);
BeanDefine beanDefine = new BeanDefine(bean);
addBean(name, beanDefine);
// add interface
Class<?>[] interfaces = beanDefine.getType().getInterfaces();
if (interfaces.length > 0) {
for (Class<?> interfaceClazz : interfaces) {
this.addBean(interfaceClazz.getName(), beanDefine);
}
}
}
/**
* Update BeanDefine
*/
public void setBean(Class<?> type, Object proxyBean) {
Assert.notNull(proxyBean);
BeanDefine beanDefine = pool.get(type.getName());
if (beanDefine != null) {
beanDefine.setBean(proxyBean);
} else {
beanDefine = new BeanDefine(proxyBean, type);
}
pool.put(type.getName(), beanDefine);
}
/**
* Add user-defined objects
*/
public void addBean(String name, BeanDefine beanDefine) {
Assert.notNull(name);
Assert.notNull(beanDefine);
// LOGGER.debug("addBean: {}", name);
if (pool.put(name, beanDefine) != null) {
LOGGER.warn("Duplicated Bean: {}", name);
}
}
/**
* Register @Component marked objects
*/
@Override
public Object addBean(Class<?> type) {
return addBean(type, true);
}
/**
* Register @Component marked objects
*/
public Object addBean(Class<?> type, boolean singleton) {
Assert.notNull(type);
return addBean(type.getName(), type, singleton);
}
/**
* Register @Component marked objects
*/
public Object addBean(String name, Class<?> beanClass, boolean singleton) {
Assert.notNull(name);
Assert.notNull(beanClass);
Assert.isFalse(beanClass.isInterface(), "Must not be interface: %s", beanClass.getName());
Assert.isFalse(Modifier.isAbstract(beanClass.getModifiers()), "Must not be abstract class: %s", beanClass.getName());
// LOGGER.debug("addBean: {} = {}", name, beanClass.getName());
BeanDefine beanDefine = this.getBeanDefine(beanClass, singleton);
if (pool.put(name, beanDefine) != null) {
LOGGER.warn("Duplicated Bean: {}", name);
}
// add interface
Class<?>[] interfaces = beanClass.getInterfaces();
if (interfaces.length > 0) {
for (Class<?> interfaceClazz : interfaces) {
if (null != this.getBean(interfaceClazz)) {
break;
}
this.addBean(interfaceClazz.getName(), beanDefine);
}
}
return beanDefine.getBean();
}
public BeanDefine getBeanDefine(Class<?> beanClass, boolean singleton) {
try {
Object object = beanClass.newInstance();
return new BeanDefine(object, beanClass, singleton);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
@Override
public <T> T getBean(Class<T> type) {
Object bean = this.getBean(type.getName());
try {
return type.cast(bean);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public Object getBean(String name) {
BeanDefine beanDefine = pool.get(name);
if (beanDefine == null) {
return null;
}
return IocKit.getBean(beanDefine);
}
@Override
public List<BeanDefine> getBeanDefines() {
return new ArrayList<BeanDefine>(pool.values());
}
@Override
public List<Object> getBeans() {
Set<String> beanNames = this.getBeanNames();
List<Object> beans = new ArrayList<Object>(beanNames.size());
for (String beanName : beanNames) {
Object bean = this.getBean(beanName);
if (null != bean) {
beans.add(bean);
}
}
return beans;
}
@Override
public Set<String> getBeanNames() {
return pool.keySet();
}
@Override
public void remove(String beanName) {
pool.remove(beanName);
}
@Override
public void remove(Class<?> type) {
pool.remove(type.getSimpleName());
}
@Override
public void clearAll() {
pool.clear();
}
}