您的位置:首页 > 编程语言 > Java开发

Spring (二)依赖注入原理 , bean 作用域, 其他配置

2017-09-01 09:41 686 查看
Spring (二)依赖注入原理 , bean 作用域, 其他配置

1、 依赖注入原理

public class JmiracleClassPathXmlApplicationContext {
private List<BeanDefinition> bds = new ArrayList<BeanDefinition>();
private Map<String, Object> sigletons = new HashMap<String, Object>();

public JmiracleClassPathXmlApplicationContext (String filename) {
readXml(filename);
instanceBeans();
injuectObject();
}

private void injuectObject() {
for ( BeanDefinition beanDefinition : beanDefinition ) {
Object bean = sigletons.get(beanDefinition.getId());
if ( bean != null ) {
try {
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for ( PropertyDefinition propertyDefinition : beanDefinition.getProperties() ) {
for ( PropertyDescriptor propertyDesc : ps ) {
if ( propertyDefinition.getName().equals(propertyDesc.getName())) {
// 获取属性的setter方法
Method setter = propertyDesc.getWriteMethod();
if ( setter != null ) {
Object value = sigletons.get(propertyDefinition.getRef());
setter.setAccessible(true); // 如果setter为private
setter.invoke(bean, value); //把引用注入到属性
}
}
}
}
} catch (Exception e ) {
// TODO
}
}
}
}

private void readXml(String filename) {
SAXReader reader = new SAXReader();
Document doc = null;
try {
URL xmlPath = this.getClass().getClassLoader().getResource(filename); // 可以获取bin目录下的资源文件
doc = reader.read(xmlPath);
Map<String, String> nsMap = new HashMap<String, String>();
// 加入命名空间
nsMap.put("ns", "http://www.springframework.org/schema/beans");
// 创建beans/bean查询路径
XPath xsub = document.createXPath("//ns:beans/ns:bean");
// 设置命名空间
xsub.setNamespaceURIs(nsMap);
// 获取文档下所有的bean
List<Element> beans = xsub.selectNodes(document);
for (Element element : beans) {
String id = element.attributeValue("id");
String clazz = element.attributeValue("class");
BeanDefinition d = new BeanDefinition(id, clazz);
XPath propertySub = element.createXPath("ns:property");
propertySub.setNamespaceURIs(nsMap);
List<Element> propertyBeans = propertySub.selectNodes(element);
for ( Element propE : propertyBeans ) {
String pName = propE.attributeValue("name");
String pRef = propE.attributeValue("ref");
PropertyDefinition pd = new PropertyDefinition(pName, pRef);
bds.getProperties().add(pd);
}

bds.add(d);
}
} catch (Exception e) {
e.printStackTrace();
}
}

private void instanceBeans() {
for ( BeanDefinition beanD : bds ) {
try {
if ( beanD.getClassname() != null && !"".equals(beanD.getClassname())) {
// 通过反射获取类名对应的实例
sigletons.put(beanD.getId(), Class.forName(beanD.getClassname()).newInstance());
}
}catch (Exception e) {
e.printStackTrace()
}
}
}

public Object getBean(String beanName) {
return this.sigletons.get(beanName);
}

public static void main(String[] args) {
JmiracleClassPathXmlApplicationContext ctx = new JmiracleClassPathXmlApplicationContext("application.xml");
IService service = (IService)ctx.getBean("service");
service.sayHello();
}
}

class BeanDefinition {
private String id;
private String classname;
private List<PropertyDefinition> properties = new ArrayList<PropertyDefinition>();

public BeanDefinition (String id, String classname) {
this.id = id;
this.classname = classname;
}

public void setProperties(List<PropertyDefinition> properties) {
this.properties = properties;
}
public List<PropertyDefinition> getProperties() {
return this.properties;
}
public String getId() {
return this.id;
}
public void setId(String id ) {
this.id = id;
}

public String getClassname () {
return this.classname;
}

public void setClassname(String classname ) {
this.classname = classname;
}
}

class PropertyDefinition {
private String name;
private String ref;

public BeanDefinition (String name, String ref) {
this.name = name;
this.ref = ref;
}
public String getName() {
return this.name;
}
public void setName(String name ) {
this.name = name;
}

public String getRef () {
return this.ref;
}

public void setRef(String ref ) {
this.ref = ref;
}
}

interface IService {
void sayHello();
}

class ServiceImpl implements IService {
private ServiceDao serviceDao;

public void setServiceDao(ServiceDao serviceDao) {
this.serviceDao = serviceDao;
}

public ServiceDao getServiceDao() {
return this.serviceDao;
}
public void sayHello () {
serviceDao.sayHello();
}
}
interface ServiceDao {
void sayHello();
}
class ServiceDaoBean {
public void sayHello () {
System.out.println("ServiceDaoBean -> sayHello");
}
}

// application.xml
<bean id="serviceDao" class="ServiceDaoBean" ></bean>
<bean id="service" class="ServiceImp" >
<property name="serviceDao" ref="serviceDao"></property> //name必须与成员属性名称一样
</bean>


2、 bean 作用域

a.  singleton : 在每个Spring IOC容器中一个bean定义只有一个对象实例,默认情况下会在容器启动时初始化bean
JmiracleClassPathXmlApplicationContext ctx = new JmiracleClassPathXmlApplicationContext("application.xml");

可以指定bean节点的lazy-init="true"来延迟初始化bean,这样,只有第一次获取bean才会初始化bean
<bean id="service" class="ServiceImpl" lazy-init="true"></bean>

如果想对所有bean都应用延迟生效,可以在父节点beans中设置 default-lazy-init="true"
<beans default-lazy-init="true"></beans>

b.  prototype : 每次从容器获取bean都是新对象
<bean id="service" class="ServiceImpl" scope="prototype"></bean>

c.  request、session、 global session 都是浏览器的配置


3、 其他配置

init-method="init" 初始化方法: 可以用于在创建bean对象时初始化对象参数
destory-method="destory" 释放资源方法: 可用于释放对象中的资源
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring bean