Spring4深入理解IOC&DI04----Bean配置方式(全类名,工厂方法,FactoryBean),配置形式(基于XML和注解),泛型依赖注入
2016-09-16 19:13
1491 查看
参考代码下载github:https://github.com/changwensir/java-ee/tree/master/spring4
1-1.通过静态工厂方式配置Bean
--•调用静态工厂方法创建Bean是将对象创建的过程封装到静态方法中.当客户端需要对象时,只需要简单地调用静态方法,而不同关心创建对象的细节.
--•要声明通过静态方法创建的 Bean,需要在Bean的class属性里指定拥有该工厂的方法的类,同时在factory-method属性里指定工厂方法的名称.最后,使用<constrctor-arg>元素为该方法传递方法参数.
1-2.通过实例工厂方式配置Bean
•实例工厂方法:
将对象的创建过程封装到另外一个对象实例的方法里.当客户端需要请求对象时,只需要简单的调用该实例方法而不需要关心对象的创建细节.
•要声明通过实例工厂方法创建的 Bean
–在 bean
的factory-bean属性里指定拥有该工厂方法的Bean
–在 factory-method属性里指定该工厂方法的名称
–使用 construtor-arg元素为工厂方法传递方法参数
•Spring 中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean,即FactoryBean.
•工厂 Bean 跟普通Bean不同,其返回的对象不是指定类的一个实例,其返回的是该工厂Bean的getObject方法所返回的对象
在 classpath 中扫描组件
•组件扫描(componentscanning): Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件.
•特定组件包括:
–@Component: 基本注解,标识了一个受Spring管理的组件
–@Respository:标识持久层组件
–@Service: 标识服务层(业务层)组件
–@Controller: 标识表现层组件
•对于扫描到的组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写.也可以在注解中通过value属性值标识组件的名称
•当在组件类上使用了特定的注解之后,还需要在Spring的配置文件中声明<context:component-scan>:
–base-package 属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里及其子包中的所有类.
–当需要扫描多个包时,
可以使用逗号分隔.
–如果仅希望扫描特定的类而非基包下的所有类,可使用 resource-pattern属性过滤特定的类,示例:
–<context:include-filter>子节点表示要包含的目标类
–<context:exclude-filter>子节点表示要排除在外的目标类
–<context:component-scan>下可以拥有若干个<context:include-filter>和<context:exclude-filter>子节点
以下 类那放在这个文件下Spring4_IOC.annotation
1).使用 @Autowired自动装配Bean
•@Autowired注解自动装配具有兼容类型的单个Bean属性
–构造器,普通字段(即使是非public),一切具有参数的方法都可以应用@Authwired注解
–默认情况下,所有使用@Authwired注解的属性都需要被设置.当Spring找不到匹配的Bean装配属性时,会抛出异常,若某一属性允许不被设置,可以设置@Authwired注解的required属性为false
–默认情况下,当IOC容器里存在多个类型兼容的Bean时,通过类型的自动装配将无法工作.此时可以在@Qualifier注解里提供Bean的名称.Spring允许对方法的入参标注@Qualifiter已指定注入Bean的名称
–@Authwired注解也可以应用在数组类型的属性上,此时Spring将会把所有匹配的Bean进行自动装配.
–@Authwired注解也可以应用在集合属性上,此时Spring读取该集合的类型信息,然后自动装配所有与之兼容的Bean.
–@Authwired注解用在java.util.Map上时,若该Map的键值为String,那么Spring将自动装配与之Map值类型兼容的Bean,此时Bean的名称作为键值
2).使用 @Resource或@Inject自动装配Bean
•Spring 还支持
@Resource和@Inject注解,这两个注解和@Autowired注解的功用类似
•@Resource 注解要求提供一个Bean名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为Bean的名称
•@Inject 和
@Autowired注解一样也是按类型匹配注入的Bean,但没有reqired属性
•建议使用 @Autowired注解
整合多个配置文件
•Spring 允许通过
<import>将多个配置文件引入到一个文件中,进行配置文件的集成。这样在启动Spring容器时,仅需要指定这个合并好的配置文件就可以。
•import元素的resource属性支持Spring的标准的路径资源
一、Bean的配置方式
Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean1-1.通过静态工厂方式配置Bean
--•调用静态工厂方法创建Bean是将对象创建的过程封装到静态方法中.当客户端需要对象时,只需要简单地调用静态方法,而不同关心创建对象的细节.
--•要声明通过静态方法创建的 Bean,需要在Bean的class属性里指定拥有该工厂的方法的类,同时在factory-method属性里指定工厂方法的名称.最后,使用<constrctor-arg>元素为该方法传递方法参数.
1-2.通过实例工厂方式配置Bean
•实例工厂方法:
将对象的创建过程封装到另外一个对象实例的方法里.当客户端需要请求对象时,只需要简单的调用该实例方法而不需要关心对象的创建细节.
•要声明通过实例工厂方法创建的 Bean
–在 bean
的factory-bean属性里指定拥有该工厂方法的Bean
–在 factory-method属性里指定该工厂方法的名称
–使用 construtor-arg元素为工厂方法传递方法参数
/** * InstanceCarFactory:实例工厂方法 * 实例工厂的方法,即需要先创建工厂本身,再调用工厂的实例方法来返回bean的实例 * * @author Lcw 2015/11/12 */ public class InstanceCarFactory { private Map<String, Car> cars = null; public InstanceCarFactory() { cars = new HashMap<String, Car>(); cars.put("audi", new Car("audi", 500000)); cars.put("ford", new Car("ford", 600000)); } public Car getCar(String brand) { return cars.get(brand); } }
/** * StaticCarFactory:静态工厂方法:直接调用某一个类的静态方法就可以返回Bean实例 */ public class StaticCarFactory { private static Map<String , Car> cars = new HashMap<String, Car>(); static { cars.put("audi",new Car("audi", 30000)); cars.put("ford",new Car("ford", 40000)); } //静态工厂方法: 注意:要在配置文件XML里配置Car而不是StaticCarFactory public static Car getCar(String name) { return cars.get(name); } }
<?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 http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <!--通过静态工厂方法来配置bean, 注意不是配置静态工厂方法实例,而是配置bean实例--> <!--factory-method: 指向静态工厂方法的名字 constructor-arg:如果工厂方法需要传入参数,则使用constructor-arg来配置参数--> <bean id="car1" class="Spring4_IOC.bean.factory.StaticCarFactory" factory-method="getCar"> <constructor-arg value="audi"/> </bean> <!--配置实例工厂的实例--> <bean id="carFactory" class="Spring4_IOC.bean.factory.InstanceCarFactory"/> <!-- 通过实例工厂方法来配置bean--> <bean id="car2" factory-bean="carFactory" factory-method="getCar"> <constructor-arg value="ford"/> </bean> </beans>
/** * Bean 的配置方式:-、通过全类名(反射);二、通过工厂方法(静态工厂方法 & 实例工厂方法);三、FactoryBean * * 静态工厂方法:直接调用某一个类的静态方法就可以返回Bean实例 * 实例工厂方法:实例工厂的方法,即需要先创建工厂本身,再调用工厂的实例方法来返回bean的实例 */ @Test public void testStaticFactory() { ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring4_IOC/beans-factory.xml"); //测试静态工厂方法 Car car1 = (Car) ctx.getBean("car1"); System.out.println(car1); //实例工厂方法 Car car2 = (Car) ctx.getBean("car2"); System.out.println(car2); }1-3.实现 FactoryBean 接口在 Spring IOC 容器中配置 Bean
•Spring 中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean,即FactoryBean.
•工厂 Bean 跟普通Bean不同,其返回的对象不是指定类的一个实例,其返回的是该工厂Bean的getObject方法所返回的对象
/** * CarFactoryBean:自定义的factoryBean需要实现FactoryBean */ public class CarFactoryBean implements FactoryBean<Car> { private String brand; public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public CarFactoryBean() { } //下面是三个实现方法 //返回bean的对象 public Car getObject() throws Exception { return new Car("BMW" , 500000); } //返回bean的类型Class<?> 中?表示一个未知的类 public Class<?> getObjectType() { return Car.class; } public boolean isSingleton() { return true; } }
<?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 http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <!-- 通过factoryBean来配置Bean的实例 class:指向FactoryBean的全类名 property:配置FactoryBean的属性 但实际返回的实例确是FactoryBean的getObject()返回的实例--> <bean id="car" class="Spring4_IOC.bean.CarFactoryBean"> <property name="brand" value="BMW"/> </bean> </beans>
/** * Bean 的配置方式:-、通过全类名(反射);二、通过工厂方法(静态工厂方法 & 实例工厂方法);三、FactoryBean * * 测试FactoryBean * Spring 中有两种类型的 Bean, 一种是普通Bean, 另一种是工厂Bean, 即FactoryBean */ @Test public void testFactoryBean() { ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring4_IOC/beans-beanFactory.xml"); Car car = (Car) ctx.getBean("car"); //注意这个在类是Car! System.out.println(car); }
二、Bean的配置形式
配置形式:基于 XML 文件的方式;基于注解的方式(基于注解配置 Bean;基于注解来装配 Bean 的属性)在 classpath 中扫描组件
•组件扫描(componentscanning): Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件.
•特定组件包括:
–@Component: 基本注解,标识了一个受Spring管理的组件
–@Respository:标识持久层组件
–@Service: 标识服务层(业务层)组件
–@Controller: 标识表现层组件
•对于扫描到的组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写.也可以在注解中通过value属性值标识组件的名称
•当在组件类上使用了特定的注解之后,还需要在Spring的配置文件中声明<context:component-scan>:
–base-package 属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里及其子包中的所有类.
–当需要扫描多个包时,
可以使用逗号分隔.
–如果仅希望扫描特定的类而非基包下的所有类,可使用 resource-pattern属性过滤特定的类,示例:
–<context:include-filter>子节点表示要包含的目标类
–<context:exclude-filter>子节点表示要排除在外的目标类
–<context:component-scan>下可以拥有若干个<context:include-filter>和<context:exclude-filter>子节点
以下 类那放在这个文件下Spring4_IOC.annotation
@Component public class TestObject { }respository接口跟实现类
public interface UserRepository { void save(); }
//接口实现一般用接口名 @Repository("userRepository") public class UserRepositoryImpl implements UserRepository { public void save() { System.out.println("UserRepository Save..."); } }Service层跟controller
@Service public class UserService { //@Autowired(required=false) //如果没有这个类,输出为null @Autowired private UserRepository userRepository; public void add() { System.out.println("UserService add..."); userRepository.save(); } }
@Controller public class UserController { @Autowired private UserService userService; public void execute() { System.out.println("UserController execute..."); userService.add(); } }
<?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.xsd"> <!--指定Spring IOC容器扫描的包--> <!--可以通过resource-pattern指定扫描的资源--> <!--<context:component-scan base-package="Spring4_IOC.annotation" resource-pattern="repository/*.class"></context:component-scan>--> <!--exclude-filter: 子节点指定排除哪些指定表达式的组件--> <!--include-filter:子节点指定包含哪些表达式的组件,该子节点需要use-default-filters="false"配合使用--> <context:component-scan base-package="Spring4_IOC.annotation" > <!--<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>--> <!--<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>--> <!--<context:exclude-filter type="assignable" expression="com.changwen.spring4.annotation.repository.UserRepository"/>--> <!--<context:include-filter type="assignable" expression="com.changwen.spring4.annotation.repository.UserRepository"/>--> </context:component-scan> </beans>
@Test public void testAnnotation() { ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring4_IOC/beans-annotation.xml"); TestObject to = (TestObject) ctx.getBean("testObject"); System.out.println(to); //类UserController第一个字母小写 userController UserController userController = (UserController) ctx.getBean("userController"); System.out.println(userController); userController.execute(); UserService userService = (UserService) ctx.getBean("userService"); System.out.println(userService); UserRepository userRepository = (UserRepository) ctx.getBean("userRepository"); System.out.println(userRepository); }<context:include-filter>和<context:exclude-filter>子节点支持多种类型的过滤表达式
2-1.组件装配
•<context:component-scan>元素还会自动注册AutowiredAnnotationBeanPostProcessor实例,该实例可以自动装配具有@Autowired和@Resource、@Inject注解的属性.1).使用 @Autowired自动装配Bean
•@Autowired注解自动装配具有兼容类型的单个Bean属性
–构造器,普通字段(即使是非public),一切具有参数的方法都可以应用@Authwired注解
–默认情况下,所有使用@Authwired注解的属性都需要被设置.当Spring找不到匹配的Bean装配属性时,会抛出异常,若某一属性允许不被设置,可以设置@Authwired注解的required属性为false
–默认情况下,当IOC容器里存在多个类型兼容的Bean时,通过类型的自动装配将无法工作.此时可以在@Qualifier注解里提供Bean的名称.Spring允许对方法的入参标注@Qualifiter已指定注入Bean的名称
–@Authwired注解也可以应用在数组类型的属性上,此时Spring将会把所有匹配的Bean进行自动装配.
–@Authwired注解也可以应用在集合属性上,此时Spring读取该集合的类型信息,然后自动装配所有与之兼容的Bean.
–@Authwired注解用在java.util.Map上时,若该Map的键值为String,那么Spring将自动装配与之Map值类型兼容的Bean,此时Bean的名称作为键值
2).使用 @Resource或@Inject自动装配Bean
•Spring 还支持
@Resource和@Inject注解,这两个注解和@Autowired注解的功用类似
•@Resource 注解要求提供一个Bean名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为Bean的名称
•@Inject 和
@Autowired注解一样也是按类型匹配注入的Bean,但没有reqired属性
•建议使用 @Autowired注解
三、泛型依赖注入
•Spring 4.x 中可以为子类注入子类对应的泛型类型的成员变量的引用public class BaseRepository<T> { }
public class BaseService<T> { @Autowired protected BaseRepository<T> repository; public void add() { System.out.println("add..."); System.out.println(repository); } }
@Service public class UserService extends BaseService<User> { }
public class User { private String userName; private List<Car> cars; private String wifeName; public String getWifeName() { return wifeName; } public void setWifeName(String wifeName) { System.out.println("setWifhName: " + wifeName); this.wifeName = wifeName; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public List<Car> getCars() { return cars; } public void setCars(List<Car> cars) { this.cars = cars; } public User() { System.out.println("User's Construtor..."); } @Override public String toString() { return "User [userName=" + userName + ", cars=" + cars + "]"; } public void init(){ System.out.println("init method..."); } public void destroy(){ System.out.println("destroy method..."); } }
@Repository public class UserRepository extends BaseRepository<User>{ }配置文件
<?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/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="Spring4_IOC.di"> </context:component-scan> </beans>
/** * Spring 4.x 新特性:泛型依赖注入 */ @Test public void testDI() { ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring4_IOC/beans-generic.xml"); Spring4_IOC.di.UserService userService = (Spring4_IOC.di.UserService) ctx.getBean("userService"); System.out.println(userService); userService.add(); }
Spring4_IOC.di.UserService@225a8897 add... Spring4_IOC.di.UserRepository@65bd831f |
•Spring 允许通过
<import>将多个配置文件引入到一个文件中,进行配置文件的集成。这样在启动Spring容器时,仅需要指定这个合并好的配置文件就可以。
•import元素的resource属性支持Spring的标准的路径资源
相关文章推荐
- spring学习总结(三):IOC & DI 配置 Bean 之配置形式及依赖注入方式
- spring ioc容器注入的集中方式,以及属性注入的集中依赖,继承,使用SPEL表达式,ioc容器的生命周期,bean的几种工厂方法配置方式,bean的自动装配
- 7.10.3: 深入理解依赖关系配置---注入其他bean的方法返回值
- Spring4深入理解01----Bean配置(依赖注入和控制反转的区别)
- (spring-第3回【IoC基础篇】)spring的依赖注入-属性、构造函数、工厂方法等的注入(基于XML)
- Spring4深入理解AOP02----AOP简介,AspectJ,AOP基于注解和XML配置(5种通知,切面优先级)
- Spring4深入理解IOC&DI02----Bean配置--自动装配、bean之间的继承与依赖、使用外部属性文件
- Spring 配置bean, 注解方式配置 xml方式要生产set方法方便属性注入,注解方式不需要,利用反射机制注入
- spring、IoC控制反转和DI依赖注入入门、基于XML的Bean装配、基于注解的Bean装配
- 先码后看 spring配置bean的几种方式:xml直接配置、静态工厂、实例工厂、factory bean、注解 侵立删
- [原创]java WEB学习笔记102:Spring学习---Spring Bean配置:bean配置方式(工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean) 全类名
- Spring4深入理解01----Bean配置(依赖注入和控制反转的区别)
- 【JavaWeb-23】spring、IoC控制反转和DI依赖注入入门、基于XML的Bean装配、基于注解的Bean装配
- Spring4深入理解01----Bean配置(依赖注入和控制反转的区别)
- 原始方式:spring四种依赖注入方式 |注解方式:Spring零配置通过注解实现Bean依赖注入
- 7.10.1: 深入理解依赖关系配置---注入其他Bean的属性值
- 框架 day36 Spring3 入门,DI依赖注入,装配bean基于xml/注解, 整合Junit4,配置约束自动提示
- spring4——IOC之基于注解的依赖注入(DI )
- 【Java.Spring.Core】【IoC】基于注解的Bean装配(非XML配置)
- 7.7.2: Bean实例的创建方式及依赖配置---使用静态工厂方法创建Bean