Spring配置bean
基本
<?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:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 属性注入的方式,依赖seter方法,name2并不是属性名,而是由setName2()得来的 --> <bean id="person" class="model.Person"> <property name="name2" value="JJ"></property> </bean> <!-- 构造器注入的方式,依赖bean中对应的构造方法,可以指定顺序和类型,都不指定的话就会自动按照顺序注入,不会自动对照类型 --> <bean id="car1" class="model.Car"> <constructor-arg index="0" type="java.lang.String" value="Auto"></constructor-arg> <constructor-arg index="1" type="java.lang.String" value="DaZhong"></constructor-arg> <constructor-arg index="2" type="java.lang.Integer" value="200"></constructor-arg> </bean> <bean id="car2" class="model.Car"> <constructor-arg index="0" type="java.lang.String" value="BieKe"></constructor-arg> <constructor-arg index="1" type="java.lang.String" value="TongYong"></constructor-arg> <constructor-arg index="2" type="java.lang.Double" value="200000.0"></constructor-arg> </bean> <bean id="person_car1" class="model.Person_Car"> <constructor-arg type="java.lang.String" > <!-- 想指定的字符串中有特殊字符的情况 --> <value><![CDATA[<QQ>]]></value> </constructor-arg> <!-- ref:引用上面定义过的对象 --> <constructor-arg type="model.Car" ref="car1"></constructor-arg> <!-- 也可以以这种方式为引用对象赋值(级联的方式) --> <property name="car.price" value="1"></property> </bean> <bean id="person_car2" class="model.Person_Car"> <property name="name"> <value><![CDATA[<WW>]]></value> </property> <property name="car"> <!-- 为内部引用单独定义对象,外部引用不到,所以可以不写id --> <bean class="model.Car"> <constructor-arg index="0" value="HaFu"></constructor-arg> <constructor-arg index="1" value="ChangCheng"></constructor-arg> <constructor-arg type="java.lang.Double" value="100000.0"></constructor-arg> <property name="maxSpeed" value="100"></property> </bean> </property> <!-- 赋空值的方式 --> <property name="car.brand"><null></null></property> <property name="Car.corp" value="ZhongTai"></property> </bean> <!-- 若属性为数组或者list时的 --> <bean id="person_collectioncar" class="model.Person_CollectionCar"> <constructor-arg value="EE"></constructor-arg> <constructor-arg> <list> <ref bean="car1"/> <ref bean="car2"/> </list> </constructor-arg> </bean> <!-- 若属性为Map时的 --> <bean id="person_mapcar" class="model.Person_MapCar"> <property name="name" value="RR"></property> <property name="cars"> <map> <entry key="11" value-ref="car1"></entry> <entry key="22" value-ref="car2"></entry> </map> </property> </bean> <!-- 若属性为properties时 --> <bean id="person_propertiescar" class="model.Person_PropertiesCar"> <property name="name" value="TT"></property> <property name="cars"> <!-- 同样外部无法引用 --> <props> <prop key="33">JIYUNFEI</prop> <prop key="44">wangshu321</prop> </props> </property> </bean> <bean id="person_propertiescar2" class="model.Person_PropertiesCar"> <property name="name" value="TT"></property> <property name="cars" ref="pp"></property> </bean> <!-- 需要先打开util命名空间,可以定义properties,list,map,数组等类型的属性,方便上面引用 --> <util:properties id="pp"> <prop key="33">JIYUNFEI</prop> <prop key="55">jiyunfei</prop> </util:properties> <!-- 需要先打开p命名空间,以这种方式可以更方便定义bean --> <bean id="person_propertiescar3" class="model.Person_PropertiesCar" p:name="CC" p:cars-ref="pp"></bean> </beans>
package helloSpring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import model.Person_CollectionCar;
import model.Person_MapCar;
import model.Person_PropertiesCar;
public class Main {
public static void main(String[] args) {
// Person p = new Person();
// p.setName("Ji");
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// Person p = (Person) context.getBean("person");
// Person p = context.getBean(Person.class);
// p.hello();
/**
* ApplicationContext获取bean的三种方式
* (Person) context.getBean("person") 需要强转
* context.getBean("car1", Car.class) 不需要强转
* context.getBean(Car.class) 要求xml中这种类型只能有一个
* */
// Car car1 = context.getBean("car1", Car.class);
// Car car2 = context.getBean("car2", Car.class);
// System.out.println(car1);
// System.out.println(car2);
// Person_Car p1 = (Person_Car) context.getBean("person_car1");
// Person_Car p2 = (Person_Car) context.getBean("person_car2");
// System.out.println(p1);
// System.out.println(p2);
Person_CollectionCar person_CollectionCar = context.getBean(Person_CollectionCar.class);
Person_MapCar person_MapCar = context.getBean(Person_MapCar.class);
Person_PropertiesCar person_PropertiesCar = context.getBean("person_propertiescar",Person_PropertiesCar.class);
System.out.println(person_CollectionCar);
System.out.println(person_MapCar);
System.out.println(person_PropertiesCar);
Person_PropertiesCar person_PropertiesCar2 = context.getBean("person_propertiescar2",Person_PropertiesCar.class);
System.out.println(person_PropertiesCar2);
Person_PropertiesCar person_PropertiesCar3 = context.getBean("person_propertiescar3",Person_PropertiesCar.class);
System.out.println(person_PropertiesCar3);
}
}
自动注入
<?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:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- <bean id="address" class="autowire.Address"> <property name="city" value="AnYang"></property> <property name="street" value="EMei"></property> </bean> --> <bean id="address2" class="autowire.Address"> <property name="city" value="BeiJing"></property> <property name="street" value="ChangAn"></property> </bean> <bean id="car" class="autowire.Car"> <property name="name" value="Audi"></property> <property name="price" value="1"></property> </bean> <bean id="car2" class="autowire.Car"> <property name="name" value="Audi"></property> <property name="price" value="1"></property> </bean> <util:list id="cars"> <ref bean="car"/> <ref bean="car2"/> </util:list> <!-- 以下为person自动装配它的引用类型的属性 --> <!-- byName:通过bean的id和seter方法中的名字匹配来自动注入属性值,并且自动注入的值还可以被覆盖修改 --> <!-- byType:用过与其他Bean的类型的匹配来注入属性值,此时要求:符合匹配类型的Bean只能有一个,否则会抛异常 --> <bean id="person" class="autowire.Person" autowire="byType"> <property name="name" value="JJ"></property> <!-- <property name="address" ref="address2"></property> --> </bean> </beans>
bean的作用域
<?xml version="1.0" encoding="UTF-8"?> <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.xsd"> <!-- Bean的作用域 默认为"singleton":表示此bean时单例的,在创建ApplicationContext对象时就调用了构造方法创建 "prototype":是原型的意思。每次get到的bean都不是一个。在每次执行ctx.getBean(Car.class);时都调用构造方法新创建一个 --> <bean id="car" class="autowire.Car" scope="prototype"> <property name="name" value="Audi"></property> <property name="price" value="1"></property> </bean> </beans>
bean之间关系
<?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:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- address和address2时继承关系 若想address只是作为被继承的父Bean可以将其设置为abstract,此时address是抽象的,在获取时抛异常 --> <bean id="address" abstract="true"> <property name="city" value="AnYang"></property> <property name="street" value="EMei"></property> </bean> <bean id="address2" class="autowire.Address" parent="address"> <property name="street" value="ChangAn"></property> </bean> <!-- 依赖 --> <bean id="car" class="autowire.Car"> <property name="name" value="Audi"></property> <property name="price" value="1"></property> </bean> <bean id="car2" class="autowire.Car"> <property name="name" value="Audi"></property> <property name="price" value="1"></property> </bean> <util:list id="cars"> <ref bean="car"/> <ref bean="car2"/> </util:list> <!-- 依赖 depends-on="car" 表示person这个bean依赖与一个id为car的bean,在加载IOC容器时,若在xml中没有id为car的bean抛异常 --> <!-- 若有depends-on,则IOC容器在创建bean时会按先创建car再创建person的顺序; 若没有depends-on,有ref,那么在ref时若被引用的对象不存在,那么会在这时创建被引用的对象 若没有depends-on也没有ref,那么按照从上到下的顺序创建bean 带有scope="prototype"的bean在被用到时才会创建(被其他bean引用也算用到),且每次都创建一个新的。 --> <bean id="person" class="autowire.Person" depends-on="car"> <property name="name" value="JJ"></property> <property name="address" ref="address2"></property> </bean> </beans>
bean的生命周期
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
Perosn's constructor
setAddress
setName
BeforeInit person
AA
AfterInit person
在ClassPathXmlApplicationContext关闭或者销毁时调用BB
-->
<bean id="person" class="cycle.Person" p:address-ref="address" p:name="Ji"
init-method="AA" destroy-method="BB"
depends-on="address"></bean>
<!--
Address's constructor
setCity
setStreet
BeforeInit address
init
AfterInit address
在ClassPathXmlApplicationContext关闭或者销毁时调用destroy
-->
<bean id="address" class="cycle.Address" init-method="intit" destroy-method="destroy"
p:city="#{'HuBei'}" p:street="WuHan"
></bean>
<!--
public class PostProcessor implements BeanPostProcessor
Bean 的后置处理器
Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理.
Bean 后置处理器对 IOC 容器里的所有 Bean 实例逐一处理, 而非单一实例.
其典型应用是: 检查 Bean 属性的正确性或根据特定的标准更改 Bean 的属性.
对Bean 后置处理器而言, 需要实现BeanPostProcessor接口.
在初始化方法被调用前后, Spring 将把每个 Bean 实例分别传递给上述接口的以下两个方法:
postProcessAfterInitialization postProcessBeforeInitialization
-->
<bean class="cycle.PostProcessor"></bean>
</beans>
添加外部文件
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 以这种方式添加外部文件 classpath:db.properties(需添加context命名空间) -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 以这种方式访问外部文件中的数据 -->
<!-- 意外发现${}中用username得到的是电脑名字JI -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${name}"></property>
<property name="password" value="${passWord}"></property>
<property name="driverClass" value="${driverClass}"></property>
<property name="jdbcUrl" value="${jdbcUrl}"></property>
</bean>
</beans>
另外三种工厂方法配置bean
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
静态工厂方法配置bean的方法,要求是静态属性,静态方法
此时class="factoryPeiZhiBean.StaticFactory",为静态工厂全类名,但此时通过Address.class来getBean依然没问题
factory-method="getInstance" 返回address的静态方法
<constructor-arg value="beijing"></constructor-arg>为静态方法的参数
-->
<bean id="address" class="factoryPeiZhiBean.StaticFactory" factory-method="getInstance">
<constructor-arg value="beijing"></constructor-arg>
</bean>
<bean id="address4" class="factoryPeiZhiBean.Address" >
<property name="city" value="#{T(factoryPeiZhiBean.StaticFactory).getInstance('jiaozuo').getCity()}"></property>
<property name="street" value="#{T(factoryPeiZhiBean.StaticFactory).getInstance('beijing').getStreet()}"></property>
</bean>
<!--
工厂方法配置bean
需要先有一个factory的bean,所以此时factory中属性和方法不需要是静态
-->
<bean id="factory" class="factoryPeiZhiBean.Factory"></bean>
<!-- class="factoryPeiZhiBean.Address" 自己的全类名 -->
<bean id="address2" class="factoryPeiZhiBean.Address" factory-bean="factory" factory-method="getInstance">
<constructor-arg value="jiaozuo"></constructor-arg>
</bean>
<!--
通过FactoryBean的方式配置bean
public class FactoryBean implements org.springframework.beans.factory.FactoryBean<Address>
-->
<bean id="address3" class="factoryPeiZhiBean.FactoryBean">
<property name="shengming" value="HuBei"></property>
<property name="shiming" value="WuHan"></property>
</bean>
</beans>
spEL
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
<bean id="address" class="spEL.Address">
<!-- 表示字面量 -->
<property name="city" value="#{'beijing'}"></property>
<property name="street" value="ChangAn"></property>
</bean>
<bean id="car" class="spEL.Car">
<property name="name" value="Audi"></property>
<property name="price" value="200001"></property>
<property name="r" value="100"></property>
<!--
可以用T访问一个类的 静态 变量。
也可以级联的方式访问本bean的属性值,如下的r读出来是原本定义中的0.5而不是上面刚配置的100
也可以级联的方式访问其他bean的属性值,但该值必须是明确的,且不一定是在类定义中确定的
-->
<property name="zhouchang" value="#{T(java.lang.Math).PI * car.r * 2}"></property>
</bean>
<bean id="person" class="spEL.Person">
<property name="name" value="JJ"></property>
<!-- 等同于ref -->
<property name="car" value="#{car}"></property>
<!-- 可以使用其他bean的属性值,如果使用自己的,则为null,因为自己本身此属性就是null -->
<property name="city" value="#{address.city}"></property>
<!-- 可以使用其他bean的方法,如果使用自己的,则为null,因为ioc容器通过反射得到的bean对象的引用属性就是null -->
<property name="info" value="#{person2.getCar().panduan()}"></property>
</bean>
<bean id="person2" class="spEL.Person">
<property name="name" value="YY"></property>
<property name="car" value="#{car}"></property>
<property name="city" value="#{address.city}"></property>
<!-- 也可以使用三目运算符 -->
<property name="info" value="#{car.price > 200000 ? '金领' : '白领'}"></property>
</bean>
</beans>
用注解的方式配置bean
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 6 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> 7 8 <!-- 9 用注解的方式配置bean 10 1,需要先导入spring-aop-4.0.0.RELEASE.jar包 11 2, @Component 12 public class Aa 13 14 @Component: 基本注解, 标识了一个受 Spring 管理的组件 15 @Repository: 标识持久层组件 16 @Service: 标识服务层(业务层)组件 17 @Controller: 标识表现层组件 18 对于扫描到的组件, Spring 有默认的命名策略: 使用非限定类名, 第一个字母小写. 19 也可以在注解中通过 value 属性值标识组件的名称 20 21 @Controller :控制层,就是我们的action层 22 @Service :业务逻辑层,就是我们的service或者manager层 23 @Repository:持久层,就是我们常说的DAO层 24 @Component :(字面意思就是组件),它在你确定不了事哪一个层的时候使用。 25 其实,这四个注解的效果都是一样的,Spring都会把它们当做需要注入的Bean加载在上下文中, 26 但是在项目中,却建议你严格按照除Componen的其余三个注解的含义使用在项目中。这对分层结构的web架构很有好处!! 27 --> 28 <!-- 29 组件扫描(component scanning): Spring 能够从 classpath 下自动扫描, 侦测和实例化具有特定注解的组件. 30 base-package="annotation":指定扫描的包 31 resource-pattern="*.class":可以指定扫描 包或者子包中 适合匹配的类 32 33 --> 34 35 <context:component-scan base-package="annotation" 36 resource-pattern="*.class" use-default-filters="true"> 37 <!-- 按不同的注解 去配置指定的bean。若想只配置指定的bean要和use-default-filters="false"配合使用 38 <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/> 39 --> 40 <!-- 按不同的注解 不去配置指定的bean。 41 <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> 42 --> 43 <!-- 按不同的类 --> 44 <!-- 45 <context:include-filter type="assignable" expression="annotation.Cc"/> 46 <context:exclude-filter type="assignable" expression="annotation.Rr"/> 47 --> 48 </context:component-scan> 49 50 51 <!-- 52 @Autowired 标注在属性或者set方法上面,表示自动装配。 53 其装配是先按照类型,若有多个匹配类型(继承或者实现接口)则会按照名字。 54 若@Repository("rrr")起的名字并不规范,那么可以public void setRr(@Qualifier("rrr") Rr rr) {} 55 --> 56 </beans>
浙公网安备 33010602011771号