惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Forbes - Security
Forbes - Security
L
Lohrmann on Cybersecurity
Simon Willison's Weblog
Simon Willison's Weblog
P
Proofpoint News Feed
P
Privacy International News Feed
The Hacker News
The Hacker News
AWS News Blog
AWS News Blog
S
Securelist
P
Proofpoint News Feed
Recent Announcements
Recent Announcements
GbyAI
GbyAI
B
Blog RSS Feed
A
About on SuperTechFans
C
CXSECURITY Database RSS Feed - CXSecurity.com
Y
Y Combinator Blog
Microsoft Azure Blog
Microsoft Azure Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Cyberwarzone
Cyberwarzone
I
Intezer
T
Tor Project blog
T
The Blog of Author Tim Ferriss
The GitHub Blog
The GitHub Blog
云风的 BLOG
云风的 BLOG
Recorded Future
Recorded Future
aimingoo的专栏
aimingoo的专栏
Cisco Talos Blog
Cisco Talos Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
W
WeLiveSecurity
D
DataBreaches.Net
U
Unit 42
Project Zero
Project Zero
Martin Fowler
Martin Fowler
V
V2EX
The Last Watchdog
The Last Watchdog
Security Archives - TechRepublic
Security Archives - TechRepublic
C
Cisco Blogs
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V2EX - 技术
V2EX - 技术
Hacker News - Newest:
Hacker News - Newest: "LLM"
T
Threat Research - Cisco Blogs
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
Tenable Blog
F
Full Disclosure
T
The Exploit Database - CXSecurity.com
H
Heimdal Security Blog
Latest news
Latest news
Webroot Blog
Webroot Blog

博客园 - 樊凯

Weblogic10.3客户端jar文件 PHP5操作MySQL数据库 - 樊凯 - 博客园 Struts2拦截器 使用AppServ快速建立php运行环境 Hibernate缓存 一个关于SpringSecurity很好的参考文档 Struts2.1.6 + Spring2.5+Hibernate3.2整合 JQuery和Struts实现Ajax文件上传 struts1.x+spring2.5+JPA(hibernate)整合 使用Apache的commons-codes加密 Spring备忘(涵盖Spring2.5) Sping备忘三(涵盖Spring2.5) Spring备忘二(涵盖Spring2.5) - 樊凯 - 博客园 Spring备忘一(涵盖Spring2.5) ubuntu遇到的错误 Ubuntu命令(更新中) 异常java.lang.UnsupportedClassVersionError: Bad version number in .class file 根据ResultSetMetaData对象动态创建pojo或其集合(JDBC) 天生我牛必有用
Spring备忘四(涵盖Spring2.5)
樊凯 · 2009-05-14 · via 博客园 - 樊凯

依赖注入(IOC DI)

依赖注入的两种方式:

1. set注入

Spring要求使用set注入方式的时候,Bean需要提供一个无参数的构造方法。并提供一个属性的setter方法。例如:

package com.kay.bean;

public class UserServices {

private UserBean ub;

public void setUb(UserBean ub) {

this.ub = ub;

}

public void add(){

ub.add();

}

}

在上面的例子中UserServices类依赖与UserBean类,那么可以在配置文件中进行配置。

配置方法1:

<!-- 将userBean交给spring管理 -->

<bean id="userBean" class="com.kay.bean.UserBean"/>

<!-- 将userServics交给spring管理 -->

<bean id="userServices" class="com.kay.bean.UserServices">

<!-- 利用propterty节点进行setter方法的注入 -->

<property name="ub"><ref bean="userBean"/></property>

</bean>

在配置文件中preperty节点中的name属性指的是UserServices类中的set方法的名字,比如setXXX,和属性名字无关。ref节点的bean属性指的是要引用的一个Bean,并将引用的Bean的实例注入到UserServices类中。

配置方法2:

<bean id="userBean" class="com.kay.bean.UserBean"/>

<bean id="userServices" class="com.kay.bean.UserServices">

<property name="ub"><ref local="userBean"/></property>

</bean>

上面的配置文件将原来的ref节点中的bean属性改为了local,那么local属性要求引用的Bean必须在同一配置文件中(Spring支持多配置文件)。但是bean属性则没有这个要求。

配置方法3:

<bean id="userServices" class="com.kay.bean.UserServices">

<property name="ub">

<bean class="com.kay.bean.UserBean"/>

</property>

</bean>

上面的这种配置方式成为内部Bean配置。内部Bean的定义不需要有id或name的指定,如果你指定也会被Spring容器忽略。这样配置的缺陷是引用的Bean无法得到重用,并且内部Bean是prototype的。

配置方法4:

<bean id="userBean" class="com.kay.bean.UserBean"/>

<bean id="userServices" class="com.kay.bean.UserServices">

<property name="ub" ref="userBean"/>

</bean>

这种写法只是配置方法1的简写形式。

2. 构造方法注入

从注入方面的名称上就可以看出,这种注入方式主要利用的是构造方法。把UserServices类修改为:

package com.kay.bean;

public class UserServices {

private UserBean userBean;

public UserServices(UserBean userBean){

this.userBean = userBean;

}

public void add(){

userBean.add();

}

}

配置方法1:

<bean id="userBean" class="com.kay.bean.UserBean"/>

<bean id="userServices" class="com.kay.bean.UserServices">

<constructor-arg>

<ref bean="userBean"/>

</constructor-arg>

</bean>

上面使用了constructor-arg节点,该节点的ref子结点bean属性指定了要引用的Bean。

如果在UserServices类中有这样的构造方法:

package com.kay.bean;

public class UserServices {

private String name;

public int a;

public UserServices(String name,int a){

this.name = name;

this.a = a;

}

}

那么可以使用配置方法2和配置方法3来解决。

配置方法2:

<bean id="userServices" class="com.kay.bean.UserServices">

<constructor-arg type="java.lang.String" value="Tom"/>

<constructor-arg type="int" value="25"/>

</bean>

在配置方法2中使用type属性指定了构造方法参数的类型,value指定参数的值。

配置方法3:

<bean id="userServices" class="com.kay.bean.UserServices">

<constructor-arg index="0" value="Tom"/>

<constructor-arg index="1" value="25"/>

</bean>

在配置方法3中使用index属性指定构造方法中的参数的顺序。

使用构造方法注入还是set注入?

首先告诉你该问题没有答案!!!

使用构造方法注入的理由:

n 构造方法注入使用强依赖规定,如果不给足够的参数,对象则无法创建。

n 由于Bean的依赖都通过构造方法设置了,那么就不用写更多的set方法,有助于减少代码量。

使用set注入的理由:

n 如果Bean有很多的依赖,那么构造方法的参数列表会变的很长。

n 如果一个对象有多种构造方法,构造方法会造成代码量增加。

n 如果构造方法中有两个以上的参数类型相同,那么将很难确定参数的用途。

n ……

Spring官方更推荐使用set注入。

更多注入:

从User类来开始:

public class User {

private int age;

private String name;

private double score;

private List fav;

private Map map;

private Set set;

private Properties pro;

public void setAge(int age) {

this.age = age;

}

public void setName(String name) {

this.name = name;

}

public void setScore(double score) {

this.score = score;

}

public void setFav(List fav) {

this.fav = fav;

}

public void setMap(Map map) {

this.map = map;

}

public void setSet(Set set) {

this.set = set;

}

public void setPro(Properties pro) {

this.pro = pro;

}

}

1. 注入直接变量(基本数据类型,String类型等)

<bean id="user" class="com.kay.bean.User">

<property name="age" value="45"></property>

<property name="name" value="Tom"></property>

<property name="score" value="45.5"></property>

</bean>

或:

<bean id="user" class="com.kay.bean.User">

<property name="age">

<value>45</value>

</property>

<property name="name">

<value>Tom</value>

</property>

<property name="score">

<value>45.5</value>

</property>

</bean>

当然构造方法注入的方式也是可以的:

<bean id="user" class="com.kay.bean.User">

<constructor-arg type="int" value="45"></constructor-arg>

<constructor-arg type="double" value="45.5"></constructor-arg>

<constructor-arg type="java.lang.String" value="Tom"></constructor-arg>

</bean>

2. 集合

a) List

<property name="fav">

<list>

<value>football</value>

<value>pingpang</value>

<value>swing</value>

</list>

</property>

b) Set

<property name="set">

<set>

<value>set1</value>

<value>set2</value>

<value>set3</value>

</set>

</property>

c) Map

<property name="map">

<map>

<entry>

<key>

<value>id</value>

</key>

<value>001</value>

</entry>

<entry>

<key>

<value>name</value>

</key>

<value>jerry</value>

</entry>

</map>

</property>

d) Properties

<property name="pro">

<props>

<prop key="name">Tom</prop>

<prop key="age">15</prop>

</props>

</property>

3. Null

配置节点<null/>用于处理null值。

<property name="name">

<null></null>

</property>

上述配置相当于setName(null);

如果这样配置:

<property name="name">

<value></value>

</property>

则相当于setName(“”);

4. 使用p命名空间进行属性注入

修改配置文件的schema:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:p="http://www.springframework.org/schema/p"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-2.5.xsd">

</beans>

注入属性:

<bean id="user" class="com.kay.bean.User" p:name="tom" p:age="45" p:score="55.5">

</bean>

在上面的设置中使用了命名空间p,p:name则代表给name属性进行赋值,如果User类中有一个属性需要引用其他的Bean,则需要这样配置p:属性名-ref=”要引用的Bean”:

<bean id="userBean" class="com.kay.bean.UserBean"/>

<bean id="user" class="com.kay.bean.User" p:name="tom" p:age="45" p:score="55.5" p:userbean-ref="userBean">

</bean>

5. Bean的自动装配(注入)

Spring提供了以下四种自动装配类型:

n byName à试图在容器中寻找和需要自动装配的属性名相同的Bean(或ID)。如果没有找到,这个属性就没有被转配上。

n byType à 试图在容器中寻找一个与需要自动装配的属性类型相同的Bean。如果没有找到相符的Bean,这个属性就没有被装配,如果找到超过一个相符的Bean,会抛出org.springframework.bean.factory.UnsatisfiedDependencyException异常。

n Constructor à试图在容器中查找与需要自动装配的Bean的构造函数一致的一个或多个Bean。古国存在不确定的Bean或构造函数,容器抛出org.spingframework.beans.factory. UnsatisfiedDependencyException异常。

n Autodetect à首先尝试使用constrctor来装配,然后采用byType方式。不确定性的处理与constrctor和byType方式一样。

使用byName进行自动装配:

UserDAO类:

public class UserDAO {

public void add(){

System.out.println("使用JDBC进行添加操作");

}

}

UserServices类:

public class UserServices {

private UserDAO userDAO;

public void setUserDAO(UserDAO userDAO) {

this.userDAO = userDAO;

}

public void add(){

userDAO.add();

}

}

使用byName自动装配:

<bean id="userDAO" class="com.kay.bean.UserDAO"></bean>

<bean id="userService" class="com.kay.bean.UserServices" autowire="byName">

</bean>

在使用byName自动装配的时候,需要将Bean中注入的属性名设置为和要注入的Bean名称一样。(黄色部分)

使用byType进行自动装配:

在使用byType进行自动装配的时候,和使用byName进行装配工作方式的相同的,只不过是通过属性的类型进行寻找相关Bean进行装配的。

<bean id="userDAO" class="com.kay.bean.UserDAO"></bean>

<bean id="userService" class="com.kay.bean.UserServices" autowire="byType">

</bean>

在使用buType自动装配的时候,如果Spring找到和需要注入的Bean的类型相同的Bean个数超过了一个,Spring不会决定将哪个Bean注入,而是直接抛出异常。

使用constructor进行自动装配:

修改UserService类:

public class UserServices {

private UserDAO userDAO;

public UserServices( UserDAO userDAO)

{

this.userDAO = userDAO;

}

public void add(){

userDAO.add();

}

}

修改配置文件:

<bean id="userDAO" class="com.kay.bean.UserDAO"></bean>

<bean id="userService" class="com.kay.bean.UserServices" autowire="constructor">

</bean>

在使用constructor进行自动转配的时候,Spring容器会寻找匹配Bean的构造方法的Bean进行注入,和ByType一样,如果容器找到一个以上的匹配Bean,同样不会决定将哪个Bean进行注入,而是抛出异常。

使用autodetect自动装配:

<bean id="userService" class="com.kay.bean.UserServices" autowire="autodetect">

</bean>

将atuowire属性值设置为autodetect,那么将由Spring容器决定使用哪种装配方式。容器会先尝试使用constructor进行装配,如果失败则会使用byTyep进行装配。

在默认的情况下,Spring容器不会进行自动装配,除非在配置文件中设置了autowire属性,如果设置beans节点的default-autowire属性,那么所有的Bean都会采用自动装配。

<beans default-autowire="byName">

</beans>

采用上述设置后,所有的Bean都采用byName方式进行装配。