1.spring依赖注入
1.依赖注入的含义: Dependency Injection
通过控制反转(IOC),将对象的创建交给了spring容器来管理后,对象也应该交给spring容器来维护,即:由spring容器来对对象进行赋值。在一个bean对象中注入另外一个bean对象时,这两个bean对象都必须被spring容器管理。
2.构造函数注入:
使用类中的构造函数,给成员变量赋值。通过配置的方式,让spring框架来为我们注入。
2.1要求:类中需要提供一个对应参数列表的构造函数。
public class AccountServiceImpl implements IAccountService{
private String name ;
private Integer age;
private Date date;
public AccountServiceImpl(String name,Integer age, Date date){
this.name = name ;
this.age = age ;
this.date = date ;
}
public void setXxx(){ ... }
}
<bean id="accountServiceImpl" class="com.baidu.service.impl.AccountServiceImpl">
<consrtuctor-arg type="java.lang.String" value="张三"></consrtuctor-arg>
<constructor-arg index="1" value="23"></constructor-arg>
<constructor-arg name="date" ref="now"></constructor-arg>
</bean>
<bean id="now" class="java.util.Date"></bean>
type:指定参数在构造函数中的数据类型,如果出现多个相同数据类型,就按照参数的排序依次赋值
index:指定参数在构造函数参数列表的索引位置,从0开始
name:指定参数在构造函数中的名称,对对应名称的属性赋值,推荐使用
value:它能赋的值是普通数据类型(17种)
ref:它能赋的值是其他bean类型,必须得是在配置文件中配置过的bean,ref(refid)指定bean标签的id
3.set方法注入(推荐使用)
要求:在类中提供需要注入成员的set方法。
<bean id="accountServiceImpl" class="com.baidu.service.impl.AccountServiceImpl">
<property name="name" value="张三"></property>
<property name="age" value="23"></property>
<peoperty name="date" ref="now"></peoperty>
</bean>
name:指定参数在set方法中的名称,对应名称的属性赋值
value ref 用法同上
4.set方法注入集合属性
用法:给类中的集合成员传值,它用的也是set方法注入的方式,只不过变量的数据类型都是集合。
public class AccountServiceImpl implements IAccountService {
private String[] myStrs;
private List<String> myList;
private Set<String> mySet;
private Map<String,String> myMap;
private Properties props;
public void setXxx(){ ... }
}
<bean id="accountServiceImpl" class="com.baidu.service.impl.AccountServiceImpl">
<property name="myStrs">
<array>
<value>aaa</value>
<value>bbb</value>
</array>
</property>
<property name="myList">
<list>
<value>ccc</value>
</list>
</property>
<property name="mySet">
<set>
<value>ddd</value>
</set>
</property>
<property name="myMap">
<map>
<entry key="aaa" value="bbb"></entry>
<entry key="ccc">
<value>ddd</value>
</entry>
</map>
</property>
<property name="props">
<props>
<prop key="aaa">bbb</prop>
</props>
</property>
</bean>
注意:
1.在注入集合数据时,只要结构相同,标签可以互换。即:<array></array> = <list></list> = <set></set>
但是set标签和set集合有去重的效果, array和list没有。
2.当依赖注入时,无论使用带参构造注入还是set注入,当参数类型是普通数据类型时,注入值用value属性;当参数类型是集合类型时,property标签上只需要指定name属性,再在标签体内包裹集合标签指定值;当参数是其他bean类型时,使用ref指定引用的对象id来注入值
2.基于注解的 IOC 配置
1.bean.xml中的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.baidu">
</context:component-scan>
</beans>
2.2常用注解
2.2.1用于创建bean对象的注解,相当于: <bean id="" class="">,作用于ElementType.TYPE
@Component
作用:把资源交给Spring容器来管理。相当于在xml中配置一个bean。
属性:value:指定bean的id。如果不指定value 属性,默认bean的id是当前类的类名,首字母小写。
@Controller: 一般用于表现层的注解。
@Service: 一般用于业务层的注解。
@Repository: 一般用于持久层的注解。
他们三个注解都是@Component的衍生注解,他们的作用及属性都是一模一样的。
他们只不过是提供了更加明确的语义化。
2.2.2用于注入数据的,相当于: <property name="" ref="">、<property name="" value=""> ,
不需要set方法,底层会利用反射自动生成setter,作用于ElementType.Field
@Autowired
@Qualifier(value="id")
@Resource(name="id")
@Autowired作用:先自动按照数据类型注入,再按照变量名称注入(将变量名作为bean的ID),还是不能唯一匹配就报错。当使用注解注入属性时,set方法可以省略。它只能注入spring容器中的其他bean类型。
@Qualifier作用:解决注入迷失,在自动按照类型注入的基础之上,再按照Bean的id注入。它在给field注入时不能独立使用,必须和@Autowired 一起使用;但是给method参数注入时,可以独立使用。
属性:value:指定 bean 的 id。
@Resource(不是Spring的注解,是jdk自带的注解)作用:直接按照Bean的id注入。它也只能注入其他 bean 类型。
属性:name:指定bean的id。
如果不指定name属性,默认先根据byName来匹配,再根据byType来匹配
@Value
作用:注入普通数据类型(17种)和spring的EL表达式结果,@Value=("张三"),@Value("${username}")
属性:value:用于指定值。
2.2.3用于改变作用范围的,相当于: <bean id="" class="" scope="">,作用于ElementType.TYPE
@Scope 一般不配置,采用默认的单例
作用:指定 bean 的作用范围。
属性:value:指定范围的值。
取值:singleton(Spring默认的) prototype request session globalsession
2.2.4和生命周期相关的,相当于:<bean id="" class="" init-method="" destroy-method=""/>,作用于ElementType.METHOD
@PostConstruct 初始化方法,对象创建后调用,相当于init-method
@PreDestroy 销毁方法,对象销毁前调用,相当于destroy-method
2.2.5其他注解
1.告知spring当前类是一个注解配置类,相当于bean.xml
@Configuration 作用于ElementType.TYPE
作用:用于指定当前类是一个spring配置类, 当创建容器时会从该类上加载注解。获取容器时需要使用
new AnnotationConfigApplicationContext(有@Configuration 注解的类.class)。
属性:value:用于指定配置类的字节码,默认是当前类的字节码
2.告知spring容器需要扫描的包,相当于<context:component-scan base-package="com.baidu"/>
@ComponentScan 作用于ElementType.TYPE
作用:用于指定spring在初始化容器时要扫描的包,开启注解配置,可以扫描子包。
属性:basePackages:用于指定要扫描的包。和该注解中的value属性作用一样。
@ComponentScan(basePackages="com.baidu") / (value="com.baidu")
3.使用实例工厂创建对象
@Bean 作用于ElementType.Method
作用:该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器。通常使用这个注解创建一些由JDK提供的对象,比如DataSource,来交给spring管理
属性:name:给当前@Bean 注解方法创建的对象指定一个名称(即 bean 的 id)。
特殊用法: @Bean("runner")
public QueryRunner createQueryRunnere( @Qualifier("dataSource")DataSource ds ){ ... }
使用@Bean注解创建对象时,如果方法需要参数,会自动在spring容器中寻找,相当于默认DataSource上有一个@Autowired注解,如果注入迷失,可以使用@Qualifier注解找回
4.导入properties配置文件 作用于ElementType.TYPE
@PropertySource
作用:用于加载.properties 文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。
属性:value[]:用于指定 properties 文件位置。如果是在类路径下,需要写上 classpath:
eg: @PropertySource("classpath:jdbcConfig.properties")
相当于:<context:property-placeholder location="classpath:jdbcConfig.properties"/>
5.导入其他配置文件的配置信息
@Import
作用:用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration 注解。当然,写上也没问题。
属性:value[]:用于指定其他配置类的字节码。
eg: @Import({JdbcConfig.class})
@Configuration
@ComponentScan("com.baidu")
@PropertySource("classpath:jdbcConfig.properties")
public class AnnotationConfig {
@Value("${jdbc.driver}")
private String driverClass;
@Value("${jdbc.jdbcUrl}")
private String jdbcUrl;
@Value("${jdbc.user}")
private String user;
@Value("${jdbc.password}")
private String password;
@Bean
public JdbcTemplate createJdbcTemplate(@Qualifier("dataSource") DataSource ds){
System.out.println(ds);
return new JdbcTemplate(ds);
}
@Bean("dataSource")
public DataSource createDataSource() throws Exception {
ComboPooledDataSource dataSource= new ComboPooledDataSource();
dataSource.setDriverClass(driverClass);
dataSource.setJdbcUrl(jdbcUrl);
dataSource.setUser(user);
dataSource.setPassword(password);
return dataSource;
}
}