一、通过xml管理Bean
1、Spring提供了两种类型的IOC容器实现:
- BeanFactory:IOC容器的基本实现,面向Spring本身
- ApplicationContext:是BeanFactory的子接口,面向使用Spring框架的开发者
2、程序主要是通过Spring容器来访问容器中的Bean,ApplicationContext是Spring容器最常用的接口,该接口有如下两个实现类:
- ClassPathXmlApplicationContext:从类加载路径下搜索配置文件,并根据配置文件来创建Spring容器。
- FileSystemXmlApplicationContext: 从文件系统的相对路径或绝对路径下去搜索配置文件,并根据配置文件来创建Spring容器。
3、Bean中属性注入有两种方式
1、属性注入
- class属性是bean的全类名,通过反射的方式在IOC容器中创建Bean,所以要求Bean中必须有无参数的构造器
- 属性注入通过setter方法注入Bean的属性或依赖的对象
- 属性注入使用<property>元素,使用name属性指定Bean的属性名称,value属性或<value>子节点指定属性值构造器注入
2、构造器注入
- 属性值可以指定参数的位置和参数类型区分构造器
- 如果字面值包含特殊属性可以使用<![CDATA[字面值]]>
4、<util/>命名空间,可以集合实现复用
<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"
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">
<util:list id="cars">
<ref bean="car"/>
<ref bean="car"/>
<ref bean="car"/>
</util:list>
<util:map id="carMap">
<entry key="car1" value-ref="car"></entry>
</util:map>
</beans>
5、<p/>命名空间,p就是property的意思
<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" ref="locations"/>
<property name="order" value="1"/>
</bean>
<util:list id="locations">
<value>userinfo.properties</value>
</util:list>
<!-在导入了</p>命名空间后,等价于 ->
<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" p:locations-ref="locations" p:order="1" />
<util:list id="locations">
<value>userinfo.properties</value>
</util:list>
6、bean的自动装配
- 根据byName自动装配,byName根据bean的名字和当前bean的setter风格的属性名进行自动装配
- 根据byType自动装配,byType根据bean的类型和当前bean的属性的类型进行自动装配
7、继承Bean的配置
使用bean的parent属性指定继承哪个bean的配置。
- Spring允许继承bean的配置,被继承的bean称为父bean,继承这个父Bean的Bean称为子Bean
- 子Bean从父Bean中继承配置,包括Bean的属性配置
- 子Bean也可以覆盖从父Bean继承过来的配置
- 父Bean可以作为配置模板,也可以作为Bean实例。若只想把父Bean作为模板,可以设置<bean>的abstract属性为true,这样Spring将不会实例化这个Bean
- 并不是<bean>元素里的所有属性都会被继承,比如:autowire,abstract等
- 也可以忽略父Bean的class属性,让子Bean指定自己的类,而共享相同的属性配置,但此时abstract必须设为true
8、依赖Bean配置
- Spring允许通过depends-on属性设定Bean前置依赖的Bean,前置依赖的Bean会在本Bean实例化之前创建好
- 如果前置依赖于多个Bean,则可以通过逗号,空格的方式配置Bean的名称
9、Bean的作用域
使用bean的scope属性来配置bean的作用域。
- singleton:单例,默认值。容器初始时创建bean实例,在整个容器的生命周期内只创建这一个bean。
- prototype:原型。容器初始化时不创建bean的实例,而在每次请求时都创建一个新的Bean实例,并返回。
10、Bean的生命周期
bean中属性有init-method初始化方法和destroy-method销毁方法
11、Bean的后置处理器
自定义一个类实现 BeanPostProcessor接口,并具体提供postProcessBeforeInitialzation(Object bean,String beanName)和postProcessAfterInitialization(Object bean,String beanName)方法,其中postProcessBeforeInitialzation是在init-method之前被调用而postProcessAfterInitialization是在init-method之后被调用。参数中bean是bean的实例本身,beanName是IOC容器配置的bean的名字,返回值是实际上返回给用户的那个Bean,可以在以上两个方法中修改返回的bean,甚至返回一个新的Bean。
在配置文件中添加后置处理器的配置
<bean class="com.my.bean.cycle.MyBeanPostProcessor"></bean>
实现BeanPostProcessor接口(处理所有的bean)
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("处理后期:" + bean);
return bean;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("处理前期:" + bean);
return bean;
}
}
12、通过静态工厂方法获取Bean
通过静态工厂方法来配置Bean,不是配置静态工厂方法实例,而是配置bean实例。class属性指向静态工厂方法的全类名,factory-method指向静态工厂方法的名字,constructor-arg如果工厂方法需要传入参数,则使用constructor-arg来配置参数。
配置xml文件
<bean id="car" class="com.my.bean.factory.StaticFactory"
factory-method="getCar">
<constructor-arg value="奔驰"></constructor-arg>
</bean>
静态工厂类
public class StaticFactory {
private static Map<String, Car> map = new HashMap<String, Car>();
static {
map.put("奔驰", new Car("奔驰", 300000));
map.put("奥迪", new Car("奥迪", 300000));
}
public static Car getCar(String name) {
return map.get(name);
}
}
13、实例化工厂方法获取Bean
配置xml文件
<bean id="carFactory" class="com.my.bean.factory.IntertanceFactory"></bean>
<bean id="car1" factory-bean="carFactory" factory-method="getCar">
<constructor-arg value="奥迪"></constructor-arg>
</bean>
工厂方法
public class IntertanceFactory {
private Map<String, Car> map = null;
public IntertanceFactory() {
map = new HashMap<String, Car>();
map.put("奔驰", new Car("奔驰", 300000));
map.put("奥迪", new Car("奥迪", 300000));
}
public Car getCar(String name) {
return map.get(name);
}
}
14、实现Spring中FactoryBean
实现FactoryBean接口,实际返回的实例是getObject()方法返回的实例。
配置xml文件
<bean id="car" class="com.my.bean.factoryBean.CarFactoryBean">
<property name="name" value="奔驰"></property>
</bean>
实现FactoryBean接口
public class CarFactoryBean implements FactoryBean<Car> {
private String name = null;
public void setName(String name) {
this.name = name;
}
@Override
public Car getObject() throws Exception {
return new Car(name, 50000);
}
@Override
public Class<?> getObjectType() {
return Car.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
二、通过注解管理Bean
1、component-scan
Spring能够从classpath下自动扫描、侦测和实例化具有特定注解的组件。
特定组件包括:
- @Component:基本注解,标识了一个受Spring管理的组件
- @Respository:标识持久层组件
- @Service:标识服务层(业务层)组件
- @Controller:标识表现层组件
对于扫描到的组件,Spring有默认的命名策略,使用非限定类名第一个字母小写,也可以在注解中通过value属性值标识组件的名称。
<context:component-scan base-package="com.my" resource-pattern=""/>
- base-package:指定扫描的包
- resource-pattern:指定扫描的资源
<context:component>中有两个子节点:
- context:exclude-filter 子节点指定排除哪些指定表达式的组件。
- context:include-filter 子节点指定包含哪些表达式的组件,该子节点需要use-default-filters 配合使用,默认use-default-filters=true,扫描指定的包,如果use-default-filters=false,扫描子节点指定的包。
两个子节点中type类型:annotation:注解类型,assignable:指定类型
2、@autowired
默认情况下,@autowired是按类型注入的,所有使用@Aurowired注解的属性都需要被设置,当Spring找不到匹配的Bean装配属性时,会抛出异常。若某一属性允许不被设置,可以设置@Autowired注解的required属性为false。当IOC容器里存在多个类型兼容的Bean时,通常类型的自动装配将无法工作,此时可以在@Qualifier注解里提供Bean的名称,Spring允许对方法的入参标注@Qualifier已指定注入Bean的名称。
3、@resource
@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
@Resource装配顺序
1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
3、泛型
<?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">
<context:component-scan base-package="com.my.spring.bean.generic"></context:component-scan>
</beans>
//////////////////////////////////////////////////////////////////////////
package com.my.spring.bean.generic;
public class BaseRepository<T> {
}
//////////////////////////////////////////////////////////////////////////
package com.my.spring.bean.generic;
import org.springframework.beans.factory.annotation.Autowired;
public class BaseService<T> {
@Autowired
private BaseRepository<T> baseRepository;
public void getService() {
System.out.println("BaseService...");
System.out.println(baseRepository);
}
}
//////////////////////////////////////////////////////////////////////////////
package com.my.spring.bean.generic;
import org.springframework.stereotype.Service;
@Service
public class UserService extends BaseService<User> {
}
//////////////////////////////////////////////////////////////////////////////
package com.my.spring.bean.generic;
import org.springframework.stereotype.Repository;
@Repository
public class UserRepository extends BaseRepository<User> {
}
来源:CSDN
作者:奔跑8蜗牛_
链接:https://blog.csdn.net/chaoyue1861/article/details/103785498