在Spring的XML文件中通过一个bean标签,完成IoC的配置
bean标签介绍
bean实例化的三种方式
第一种:使用默认无参构造函数
在默认情况下:它会根据默认无参构造函数来创建对象
如果bean中没有默认无参构造函数,将会创建失败
<bean id="userService" class="com.UserServiceImpl"/>
第二种:静态工厂(了解)
使用StaticFactory类中的静态方法 createUserService创建对象,并存入spring容器
/**
* 模拟一个静态工厂,创建业务层实现类
*/
public class StaticFactory {
public static UserService createUserService{
return new UserServiceImpl();
}
}
<bean id="userService" class="com.StaticFactory" factory-method="createUserService">bean>
/**
* 模拟一个实例工厂,创建业务层实现类
* 此工厂创建对象,必须现有工厂实例对象,再调用方法
*/
public class InstanceFactory {
public UserService createUserService(){
return new UserServiceImpl();
}
}
<bean id="instancFactory" class="com.InstanceFactory">bean>
<bean id="userService" factory-bean="instancFactory" factory-method="createUserService">bean>
概述
依赖指的就是Bean实例中的属性
依赖(属性)分为:简单类型(8种基本类型和String类型)的属性、POJO类型的属性、集合数组类型的属性
依赖注入:Dependency Injection,它是spring框架核心IoC的具体实现
我们的程序在编写时,通过控制反转,把对象的创建交给了spring,但是代码中不可能出现没有依赖的情况
那如果一个bean中包含了一些属性,那么spring帮我们实例化了bean对象后,也需要将对应的属性信息进行赋值操作,这种属性赋值操作,就是所谓的依赖注入(获取值,注入属性)
依赖注入的方式
顾名思义,就是使用类中的构造函数,给成员变量赋值。注意:赋值的操作不是我们自己做的,而是通过配置的方式,让spring框架来为我们注入
public class UserServiceImpl implements UserService {
private int id;
private String name;
public UserServiceImpl(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public void saveUser(){
System.out.println("保存用户:id为"+id+",name为"+name+" Service实现")
}
}
<bean id="userService" class="com.UserServiceImpl">
<constructor-arg name="id" value="1">constructor-arg>
<constructor-arg name="name" value="zhangsan">constructor-arg>
bean>
需要配置bean标签的子标签property
需要配置bean中指定setter方法
@Autowired:
作用一:查找实例,从spring容器中根据Bean的类型(byType)获取实例
作用二:赋值,将找到的实例,装配给另一个实例的属性值
注意事项:一个java类型在同一个spring容器中,只能有一个实例
@Resource:
作用一:查找实例,从spring容器中根据Bean的名称(byName)获取实例
作用二:赋值,将找到的实例,装配给另一个实例的属性值
@Inject
本质上还是调用set方法
1.步骤一:需要先引入p名称空间
在schema的名称空间中加入该行:xmlns:p="http://www.springframework.org/schema/p"
2.步骤二: 使用p名称空间的语法
p:属性名 = ""
p:属性名-ref = ""
3.步骤三:测试
<bean id="person" class="com.Person" p:pname="老王" p:car2-ref="car2"/>
<bean id="car2" class="com.Car2">bean>
简单类型(value)
<bean id="userService" class="com.UserServiceImpl">
<property name="id" value="1">property>
<property name="name" value="zhangsan">property>
bean>
引用类型(ref)
ref就是reference的缩写,是引用的意思
<bean id="userService" class="com.UserServiceImpl">
<property name="userDao" ref="userDao">property>
bean>
<bean id="userDao" class="com.UserDaoImpl">bean>
集合类型(数组)
1.如果是数组或List集合,注入配置文件的方式是一样的
<bean id="collectionBean" class="com.CollectionBean">
<property name="arrs">
<list>
<value>aavalue>
<value>bbvalue>
<bean>bean>
list>
property>
bean>
2.如果是Set集合,注入的配置文件方式如下
<property name="sets">
<set>
set>
property>
3.如果是Map集合,注入的配置方式如下
<property name="map">
<map>
<entry key="老王" value="38">
<entry key="张三" value="38">
map>
property>
4.如果是Properties集合的方式,注入的配置如下
<property name="pro">
<props>
<prop key="name">rootprop>
<prop key="pass">123456prop>
props>
property>
<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">
<context:component-scan base-package="com.service">context:component-scan>
@Service
public class UserServiceImpl implements UserService {
}
相当于:
<bean id="" class="">
Component注解
把资源让spring管理。相当于在xml中配置一个bean
value:指定bean的id。如果不指定value属性,默认bean的id是当前类的类名,首字母小写
Controller&Service&Repository注解
他们三个注解都是针对@Component的衍生注解,他们的作用及属性都是一模一样的。他们只不过是提供了更加明确的语义化。
注意:如果注解中有且只有一个属性要赋值时,且名称是value,value在赋值时可以不写。
@Controller:一般用于表现层的注解
@Service:一般用于业务层的注解
@Repository:一般用于持久层的注解
相当于:
<property name="" ref="">
<property name="" value="">
@Autowired
@Qualifier
@Resource
@Inject
@Value
@Value("${name}")//name是properties文件中的key
private String name;
@Autowired、@Resource、@Inject区别
1.@Autowired是spring自带的,@Inject是JSR330规范实现的,@Resource是JSR250规范实现的,需要导入不同的包
2.@Autowired、@Inject用法基本一样,不同的是@Autowired有一个request属性
3.@Autowired、@Inject是默认按照类型匹配的,@Resource是按照名称匹配的
4.@Autowired如果需要按照名称匹配需要和@Qualifier一起使用,@Inject和@Name一起使用
改变bean作用范围的注解
<bean id="" class="" scope="">
value:指定范围的值。 取值:singleton prototype request session globalsession
生命周期相关注解
<bean id="" class="" init-method="" destory-method="" />
基于XML配置 | 基于注解配置 | |
---|---|---|
Bean定义 | @Component衍生类@Repository @Service @Controller | |
Bean名称 | 通过id或name指定 | @Component(“person”) |
Bean注入 | @Autowired按类型注入 @Qualifier按名称注入 | |
生命过程、Bean作用范围 | init-method destory-method范围scope属性 | @PostConstruct初始化 @PreDestory销毁 @Scope设置作用范围 |
适合场景 | Bean来自第三方,使用其他 | Bean的实现类由用户自己开发 |
想想能不能将以下这些bean的配置都从xml中去掉,并且最终将XML也去掉。如果可以,就可以脱离xml配置
<context:component-scan base-package="com.service"/>
<context:property-placeholder src="">context:property-placeholder>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" value="dataSource">property>
bean>
ApplicationContext context = new ClassPathXmlApplicationContext(“beans.xml”);
@Configuration
相当于spring的XML配置文件
从Spring3.0开始可以使用@Configuration定义配置类,可替换xml配置文件
配置类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义对象,初始化Spring容器
@Configuration
public class SpringConfiguration {
//spring容器初始化时,会调用配置类的无参构造函数
public SpringConfiguration(){
System.out.println("容器启动初始化。。。");
}
}
@Bean
相当于
标签
作用为:注册bean对象,主要用来配置非自定义的bean,比如DruidDataSource、SqlSessionFactory
@Bean标注在方法上(返回某个实例的方法)
name:给当前@Bean 注解方法创建的对象指定一个名称(即bean的id)。如果不指定,默认与标注的方法名相同
@Bean注解默认作用域为单例singleton作用域,可通过@Scope(“prototype”)设置为原型作用域
@Configuration
public class SpringConfiguration {
//spring容器初始化时,会调用配置类的无参构造函数
public SpringConfiguration(){
System.out.println("容器启动初始化。。。");
}
@Bean
@Scope("prototype")
public SqlSessionFactory userService(){
SqlSessionFactory sqlSessionFactory = new DefaultSqlSessionFactory();
sqlSessionFactory.setxxx();
return sqlSessionFactory;
}
}
@ComponentScan
相当于context:component-scan标签
组件扫描器,扫描@Component、@Controller、@Service、@Repository注解的类
该注解是编写在类上面的,一般配合@Configuration注解一起使用
basePackages:用于指定要扫描的包
value:和basePackages作用一样
@Service
public class UserServiceImpl implements UserService {
@Override
public void saveUser() {
System.out.println("保存用户 Service实现");
}
}
配置类:
@Configuration
@ComponentScan(basePackages="com.service")
public class SpringConfiguration {
public SpringConfiguration() {
System.out.println("容器初始化...");
}
// @Bean
// @Scope("prototype")
// public UserService userService() {
// return new UserServiceImpl(1,"张三");
//}
}
@PropertySource
相当于context:property-placeholder标签
编写在类上面,作用是加载properties配置文件
value[]:用于指定properties文件路径,如果在类路径下,需要写上classpath
@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
/**
* 创建一个数据源,并存入spring容器中
* @return
*/
@Bean(name = "dataSource")
public DataSource createDataSource() {
try {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass(driver);
ds.setJdbcUrl(url);
ds.setUser(username);
ds.setPassword(password);
return ds;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
properties文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///spring
jdbc.username=root
jdbc.password=root
当系统中有多个配置类时怎么办?想一想之前使用XML配置的时候是如何解决该问题的
@Import
相当于spring配置文件中的
标签
用来组合多个配置类,在引入其他配置类时,可以不用再写@Configuration注解。当然,写上也没问题
value:用来指定其他配置类的字节码文件
@Configuration
@ComponentScan(basePackages = "com.spring")
@Import({JdbcConfig.class})
public class SpringConfiguration {
}
@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {
}
创建纯注解方式上下文容器
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfiguration.class);
UserService service = context.getBean(UserService.class);
service.saveUser();
<web-app>
<context-param>
<param-name>contextClassparam-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
param-value>
context-param>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>
com.SpringConfiguration
param-value>
context-param>
<listener>
<listener-class>
org.springframe.web.context.ContextLoaderListener
listener-class>
listener>
web-app>