1.Spring 配置描述:
Spring容器启动的三方面条件:
1)Spring框架的类包都已经放到应用程序的类路径下;
2) 应用程序为spring提供完备的Bean配置信息;
3) Bean的类都已经放到应用程序的类路径下;
spring容器根据Bean配置信息在容器内部建立bean定义注册表,然后根据注册表加载、实例化Bean,并建立Bean和Bean的依赖关系,最后将这些准备就绪的Bean放到Bean缓存池中,供外层应用程序调用;
关键字:Bean注册信息,Bean注册表,Bean缓存池;
2.Schema配置,拥有自己的命名空间,使配置文件更具拓展性;
3.Bean基本配置:
Spring配置文件不允许出现相同id的Bean,但可以出险多个name相同的Bean;通过getBean(beanName)获取bean时,将返回最后声明的那个bean;
若出现多个class时,可以根据getBean("com.newcore.Car"); getBean("com.newcore.Car#1");getBean("com.newcore.Car#2");依次获取;
4.依赖注入:
4.1属性注入:
前提条件:一个bean要有其对应的构造方法和Setter方法;
属性注入配置:
<bean id="car" class="com.newcore.Car">
<property name="maxSpeed" ><value>200</value></property>
<property name="maxSpeed" ><value>200</value></property>
</bean>
Spring只会检查Bean中是否有对应的Setter方法,不会检测是否有对应的name属性;故可以通过写对应的Setter()方法来制造混乱;
4.2构造函数注入:
前提条件:Bean必须提供带参的构造函数;
Car的构造方法:
public Car(String brand,String corp,double price){
this.brand=brand;
this.corp=corp;
this.price=price;
}
xml配置注入:
<bean id="car3" class="com.newcore.Car">
<constructor-arg index="0" type="java.lang.String">
<value>红旗CA72</value>
</constructor-arg>
<constructor-arg index="1" type="java.lang.String">
<value>上海一汽</value>
</constructor-arg>
<constructor-arg index="2" type="int">
<value>720000</value>
</constructor-arg>
</bean>
对于多参匹配而类型不同时,spring不会报错,而是随机选择一个可匹配的构造函数;故处理时需要特别谨慎。
4.3工厂方法注入:
非静态工厂方法:
public class CarFactory{
public Car createBinLiCar(){
Car car=new Car();
car.setBrand("宾利");
return car;
}
}
xml配置:
<bean id="carFactory" class="com.newcore.CarFactory" />
<bean id="car5" factory-bean="carFactory" factory-method="createBinLiCar"/>
静态工厂方法:
public class CarFactory{
public static Car createBinLiCar(){
Car car=new Car();
car.setBrand("宾利");
return car;
}
}
xml配置:
<bean id="car6" class="com.newcore.CarFactory" factory-method="getInstance"/>
4.4引用其他bean:
xml:
<bean id="car" class="com.newcore.car"/>
<bean id="boss" class="com.newcore.boss>
<property name="car">
<ref bean="car"></ref>
</property>
</bean>
4.5内部Bean
xml:
<bean id="boss" class="com.newcore.boss">
<property>
<bean>
<property name="maxSpeed" value="200"/>
<property name="price" value="20000.00">
<property name="brand"><null/></property> //注入null
</bean>
</property>
</bean>
4.6集合类属性
List:
<bean id="boss1" class="com.newcore.boss">
<property>
<list>
<value>吃饭</value>
<value>睡觉</value>
<value>打豆豆</value>
</list>
</property>
</bean>
Set:
<bean id="boss2" class="com.newcore.boss">
<property>
<set>
<value>瓜子</value>
<value>糖块</value>
<value>小板凳</value>
</set>
<property/>
</bean>
Map:
<bean id="boss3" class="com.newcore.boss">
<property name ="jobs">
<map>
<entry>
<key><value>AM</value></key>
<value>会见客户</value>
</entry>
<entry>
<key><value>PM</value></key>
<value>公司内部会议</value>
</entry>
</map>
</property>
</bean>
4.7集合合并:
<bean id="parentBoss" abstract="true" class="com.newcore.Boss">
<property name="hoppy">
<set>
<value>看报</value>
<value>喝茶</value>
<value>写代码</value>
</set>
</property>
</bean>
<bean id="childBoss" parent="parentBoss">
<property name="hoppy">
<set merge="true">
<value>聊妹</value>
<value>逛街</value>
</set>
</property>
</bean>
4.8bean之间的关系
继承:
<bean id="abstractCar" class="com.newcore.Car">
<property name="brand" value="红旗"></property>
<property name="price" value="2000"></property>
<property name="color" value="黑色"></property>
</bean>
<bean id="car1" parent="abstractCar">
<property name="color" value="红色"></property>
</bean>
依赖:
<bean id="boss" class="com.newcore.boss" depends-on="carInit"></bean>
<bean id="car" class="com.newcore.car"></bean>
通过depends-on使在创建boss的bean之前必须先创建car;
4.9整合多个配置文件:
beanall.xml:
<import resource="classpath:config/bean.xml"/>
<import resource="classpath:config1/bean.xml"/>
//默认加载路径
ApplicationContext context=new ClassPathXmlApplicationContext("classpath:configAll/beanall.xml");
一个XML配置文件可以通过<import>组合多个外部的配置文件;
4.10使用注解定义Bean;
@Component("userDao")
public class UserDao{
..................
}
等价于在XML中注入:
<bean id="userDao" class="com.newcore.UserDao" />
除此之外,spring提供了3个基本功能和@Component相同的注解;
@Repository: 用于对DAO实现类进行标注;
@Service:用于对Service实现类进行标注;
@Controller:用于对Controller实现类进行注解;
那么这些定义注解类是怎么应用的呢?spring提供了一个context的命名空间,可以用来定义扫描注解类;
<context: component-scan base-package="com.newcore"/> //spring会自动扫描com.newcore下所有的注解类并完成bean定义;
4.11自动装配bean
使用@Autowired进行自动注入;
@Service
public class LogonService{
//通过注解@Autowired注入LogDao;
@Autowired
private LogDao logDao;
}
@Autowired默认按类型匹配方式,在容器查找匹配的bean;当有且仅有一个匹配的bean时,Spring将其注入到@Autowired标注的变量中;
当找不到匹配的bean时,spring会报异常:NoSuchBeanDefinitionException;如果试图忽略该异常,则可以使用:
@Autowired(required=false)
当出现多个匹配的bean时,为了能够指定需要注入的bean,可以使用@Qualifier注解来指定bean来进行选择性注入;
@Service
public class LogonService{
//通过注解@Autowired注入LogDao;
@Autowired
@Qualifier("userDao")
private LogDao logDao;
}
使用@Autowired对方法进行标注:
@Autowired
public void init(@Qualifier("userDao" UserDao userDao,LogDao logDao)){
}
以上UserDao会注入一个名为userDao的Bean;LogDao注入LogDao类型的Bean;
一般情况下,在Spring容器中大部分的Bean都是单例的,所以一般都无需通过@Repository、@Service等注解的value属性来指定名称;也不需要用@Qualifer来指定名称;
@Resource与@Autowired注解功能相似,它是通过名称匹配来进行注入的;
在对bean进行配置时,我们可以通过init-method和destory-method属性指定Bean的初始化及容器销毁前调用的方法,同样也可以使用注解的方式来实现;
@PostConstruct初始化方法;@PerDestroy销毁方法;可以在一个bean中定义多个注解方法:
public class Boss{
private Car car;
public Boss(){
System.out.println("construct...........");
}
@Autowired
private void setCar(Car car){
System.out.println("execute in setCar");
this.car=car;
}
@PostConstruct
private void init1(){
System.out.println("execute in init1");
}
@PostConstruct
private void init2(){
System.out.println("execute in init2");
}
@PreDestory
private void destory1(){
System.out.println("execute in destory1");
}
@PreDestory
private void destory2(){
System.out.println("execute in destory2");
}
}
执行该测试类的运行结果:
construct...........
execute in setCar
execute in init1
execute in init2
execute in destory1
execute in destory2
由此可见spring容器是先调用Boss的构造函数实例化bean;再通过@Autowired进行自动注入;然后再执行@PostConstruct标注的初始化方法;在容器关闭时,执行@PreDestory标注的方法;
4.12Spring的配置除了使用配置文件外,还可以通过Java类来实现配置,但实际用的挺少;暂不做研究;