注释用法
@Required
用于setter方法上,它表明受影响的 bean 属性在配置时必须放在 XML 配置文件中,否则容器就会抛出一个BeanInitializationException 异常。
public class Student{ private String name; private int age; @Required public void setAge(Integer age) { this.age = age; } public Integer getAge() { return age; } @Required public void setName(String name) { this.name = name; } public String getName() { return name; } }
//xml配置文件里没有配置age这个属性,会报BeanInitializationException的异常。 <context:annotation-config/> <bean id="student" class="Student"> <property name="name" value="lph"/> </bean>
@Autowired
默认按照类型方式进行bean匹配
对属性注释,用来替代setter方法
对setter方法注释
对构造函数注释public class Customer { @Autowired //对属性注释 private Person person; private int type; private String action; @Autowired //对setter方法注释 public setPerson(Person person){ this.persion=persion; } @Autowired //对构造函数注释 public Customer(Person person) { this.person = person; } }
//@Autowired注解是通过匹配数据类型自动装配Bean。 <bean id="CustomerBean" class="com.x'x'x'x.common.Customer"> <property name="action" value="buy" /> <property name="type" value="1" /> </bean> <bean id="PersonBean" class="com.x'x'x'x.common.Person"> <property name="name" value="xx" /> <property name="address" value="address ABC" /> <property name="age" value="29" /> </bean>
使用扫描器来扫描包,省去在配置文件里配置相关bean
<context:component-scan base-package="xxx.xxxx.xxxxxx.xxxx"/>
依赖检查
默认情况下,@Autowired将执行相关检查,以确保属性已经装配正常。当Spring无法找到匹配的Bean装配,它会抛出异常。要解决这个问题,可以通过 @Autowired 的“required”属性设置为false来禁用此检查功能。public class Customer { @Autowired(required=false)//即使没有匹配的bean,spring也不会报错 private Person person; private int type; private String action; //getter and setter methods }
@Qualifier
创建多个具有相同类型的 bean 时,想要用一个属性只为它们其中的一个bean进行装配,使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱。
public interface Parent(){ public void iAmParent(){} }
@Component public class mother implements Parent{ public void iAmParent(){ ....... }
@Component public class father implements Parent{ public void iAmParent(){ ....... } }
@Service public class SequenceServiceImpl implements SequenceService { //此处会报错,因为parent有两个实现类father和mother @Resource private Parent parent; }
此时我们可以用@Qualifier
@Service public class SequenceServiceImpl implements SequenceService { //使用@Qualifier指定bean @Qualifier(name="father") private Parent parent; }
@Resource
JSR-250规范定义的注解
和@Autowired作用类似,只不过@Autowired是byType的方式自动注入,@Resource默认自动注入的方式为byName
@Resource装配顺序:
1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
@Bean @Configuration @Import 来代替xml配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="helloBean" class="com.xxx.hello.impl.HelloWorldImpl">
</beans>
**等效于以下JavaConfig的配置:**
@Configuration
public class AppConfig {
@Bean(name="helloBean")
public HelloWorld helloWorld() {
return new HelloWorldImpl();
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<import resource="config/customer.xml"/>
<import resource="config/scheduler.xml"/>
</beans>
**效于 @Import 功能**
@Configuration
@Import({ CustomerConfig.class, SchedulerConfig.class })
public class AppConfig {}
Spring自动扫描组建
启用Spring组件扫描功能。
<context:component-scan base-package="xx.xxx.xxxx"/>
使用@Component注释来表示这是类是一个自动扫描组件。
@Component public class CustomerDAO { @Override public String toString() { return "Hello , This is CustomerDAO"; } }
DAO层,添加@Component,表明这也是一个自动扫描组件。
@Component public class CustomerService { @Autowired CustomerDAO customerDAO; @Override public String toString() { return "CustomerService [customerDAO=" + customerDAO + "]"; } }
要创建组件的自定义名称,你可以这样自定义名称:
@Service("AAA") public class CustomerService
自动扫描的组建类型(都是@Component的意思),对class注解
@Repository – 表示在持久层DAO组件。 @Service – 表示在业务层服务组件。 @Controller – 表示在表示层控制器组件。 @Component – 指示自动扫描组件。(不属于以上三者的时候使用)
Spring过滤器组件自动扫描
//include-filter 包含 <context:componnet-scan base-package="xx.xx.xxx"> <context:include-filter type="regex" expression="xx.xxx.*DAO.*"> </context> //exclude-filter 不包含
通过配置文件来配置Spring
基于构造函数的依赖注入
注入class
public class demo{ Test test; public void demo(Test test){ this.test=test; } } <bean id="demo" class="demo"> <constructor-args ref="test" /> <constructor-args ref="test2" /> </bean> //声明2个class的bean <bean id="test" class="test" /> <bean id="test2" class="test2" />
注入其他类型的值
public class demo{ public void demo(String str,int num){ ..... } } <bean id="demo" class="demo"> <constructor-args type="java.lang.String" value="axxxx" /> <constructor-args type="int" value="1" /> </bean>
通过索引注入
<bean id="demo" class="demo"> <constructor-args index="0" value="axxxx" /> <constructor-args index="1" value="1" /> </bean>
基于设置函数的注入
public class demo{ public void test(String str){ ....... } } <bean id="demo" class="demo"> <property name="str" value="this is a String" /> </bean>
注入集合
public class demo{ List array; HashMap map; Porperties prop; }
//注入list <bean id="demo" class="demo"> <property name="array"> <list> <value>1</value> <value>2</value> <list> </property>
//注入map <property name="map"> <map> <entry key="1" value="a1"/> <entry key="2" value="a2"/> </map> </property>
//注入属性 <property name="prop"> <props> <prop key="key1">xxx</prop> <prop key="key2">bbb</prop> </props> </property>
注入空值null
<bean><property name="asd"><null/></property></bean>
在Spring框架中,当一个类包含多个构造函数带的参数相同,它总是会造成构造函数注入参数类型歧义的问题。
为了解决这个问题,应该为构造函数指定的确切数据类型,通过像这样类型的属性:<bean id="CustomerBean" class="com.xxx.common.Customer"> <constructor-arg type="java.lang.String"> <value>xxx</value> </constructor-arg> <constructor-arg type="java.lang.String"> <value>188</value> </constructor-arg> <constructor-arg type="int"> <value>28</value> </constructor-arg> </bean> </beans>
自动装配
1. 默认的模式
这是默认的模式,你需要通过 ‘ref’ 属性来连接 bean。<bean id="customer" class="com.yiibai.common.Customer"> <property name="person" ref="person" /> </bean> <bean id="person" class="com.yiibai.common.Person" />
2. 按属性名称自动装配’
按属性名称自动装配。在这种情况下,由于对“person” bean的名称是相同于“customer” bean 的属性(“person”)名称,所以,Spring会自动通过setter方法将其装配 – “setPerson(Person person)“.<bean id="customer" class="com.yiibai.common.Customer" autowire="byName" /> <bean id="person" class="com.yiibai.common.Person" />
3. 按属性的数据类型自动装配
通过按属性的数据类型自动装配Bean。在这种情况下,由于“Person” bean中的数据类型是与“customer” bean的属性>(Person对象)的数据类型一样的,所以,Spring会自动通过setter方法将其自动装配。– “setPerson(Person person)“.<bean id="customer" class="com.yiibai.common.Customer" autowire="byType" /> <bean id="person" class="com.yiibai.common.Person" />
注入日期到bean属性
以下写法会报错
public class Customer { Date date; public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } }
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="customer" class="Customer"> <property name="date" value="2015-12-31" />//直接传string类型的值给value </bean> </beans>
正确的方法
factory-bean
<bean id="customer" class="Customer"> <property name="date"> <bean factory-bean="dataFormat" factory-method="parse"> <constructor-arg value="2015-12-31" /> </bean> </property> </bean>
CustomDateEditor
<bean id="dateEditor" class="org.springframework.beans.propertyeditors.CustomDateEditor"> <constructor-arg> <bean class="java.text.SimpleDateFormat"> <constructor-arg value="yyyy-MM-dd" /> </bean> </constructor-arg> <constructor-arg value="true" /> </bean> <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="java.util.Date"> <ref local="dateEditor" /> </entry> </map> </property> </bean> <bean id="customer" class="Customer"> <property name="date" value="2015-12-31" /> </bean>
PropertyPlaceholderConfigurer
在声明bean配置文件和提供一个PropertyPlaceholderConfigurer映射到“database.properties”属性文件。
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location"> <value>database.properties</value> </property> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean>
Bean的切面处理
init-method 指定一个方法,在实例化 bean 时,调用该方法。
destroy-method 指定一个方法,从容器中移除 bean 之后,调用该方法。
singleton 和 prototype的区别( http://wiki.jikexueyuan.com/project/spring/bean-scopes.html)<bean id="..." class="...." init-method="..." (destroy-method) scope="..." lazy-init="..." destroy-method="..." />
public example implements InitializingBean{ //实现InitializingBean接口,bean 初始化时可调用的初始化方法 public void do(){} } public example implements DisposableBean{ //实现DisposableBean接口,bean 销毁时可调用的初始化方法 public void do(){} }
两种后处理方法
Bean后处理器
Bean后处理器会在Bean实例创建成功之后,对Bean实例进行进一步的增强处理。
Bean后处理器必须实现BeanPostProcessor接口,同时必须实现该接口的两个方法。public example implements BeanPostProcessor{ //该方法的第一个参数是系统即将进行后处理的Bean实例,第二个参数是该Bean的配置id Object postProcessBeforeInitialization(Object bean, String name) throws BeansException: Object postProcessAfterinitialization(Object bean, String name) throws BeansException: }
容器后处理器
容器后处理器必须实现BeanFactoryPostProcessor接口,并实现该接口的一个方法
public example implements BeanFactoryPostProcessor{ postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory){} }
Bean可以继承
<bean id="parent" class="....."> <property name="test" value="tttt" /> </bean> <bean id="child" class="....." parent="parent"> <property name="test1" value="tttt" /> </bean>