创建应用对象之间协作关系的行为通常称为装配(wiring),这也是依赖注入(DI)的本质。
Spring提供了三种装配bean的方式
- 在XML中进行显示配置;
- 在Java中进行显示配置;
- 隐式的bean发现机制和自动装配
自动装配bean
自动装配优势:
便利,自动化装配,隐式配置代码量少。
自动装配限制:
基本数据类型的值、字符串字面量、类字面量无法使用自动装配来注入。
装配依赖中若是出现匹配到多个bean(出现歧义性),装配将会失败。
Spring实现自动装配两个步骤:
组件扫描(component scanning):Spring会扫描@Component注解的类,并会在应用上下文中为这个类创建一个bean。
自动装配(autowiring):Spring自动满足bean之间的依赖。
使用到的注解:
@Component:表明这个类作为组件类,并告知Spring要为这个类创建bean。默认bean的id为第一个字母为小写类名,可以用value指定bean的id (@Component("userDao"))。
@Configuration:代表这个类是配置类。
@ComponentScan:启动组件扫描,默认会扫描所在包以及包下所有子包中带有@Component注解的类,并会在Spring容器中为其创建一个bean。可以用basePackages属性指定包。
@ComponentScan("com.test")
@ComponentScan(basePackages={"com.test","com.sys"})
@ComponentScan(basePackageClasses={UserDaoImpl.class,UserServiceImpl.class})
@RunWith(SpringJUnit4ClassRunner.class):以便在测试开始时,自动创建Spring应用上下文。
@ContextConfiguration:告诉在哪加载配置。
@Autowired:将一个类的依赖bean装配进来。
首先创建两个接口以及他们的实现类,实现类需要用@Component进行注解:
public interface UserDao {
public void save(String name);
}
@Component
public class UserDaoImpl implements UserDao {
@Override
public void save(String name) {
// TODO Auto-generated method stub
System.out.println("保存了数据:" + name);
}
}
public interface UserService {
public void getName(String name);
}
@Component
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public void getName(String name) {
userDao.save(name);
}
}
spring默认是不启用组件扫描的,实现组件自动扫描方式有两种:
- 可以在XML中配置加上<context:component-scan base-package="xx"/>。
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 扫描路径 -->
<context:component-scan base-package="com.test"> </context:component-scan>
</beans>
测试类:
//SpringJUnit4ClassRunner测试用,测试开始的时候自动创建Spring的应用上下文。
@RunWith(SpringJUnit4ClassRunner.class)
//测试用,去指定类加载配置
@ContextConfiguration(locations="spring.xml")
public class UserTest {
@Autowired
private UserService userService;
@Test
public void test() {
userService.getName("zhangsan");
}
}
- 在新建一个配置类,类中可以什么不用写,在配置类上加上@ComponentScan注解,spring会自动扫描改配置类所在的包,一般应该倾向xml配置。
配置类:
@Configuration
@ComponentScan
public class UserConfig {
}
测试类:
//SpringJUnit4ClassRunner测试用,测试开始的时候自动创建Spring的应用上下文。
@RunWith(SpringJUnit4ClassRunner.class)
//测试用,去指定类加载配置
@ContextConfiguration(classes = UserConfig.class)
public class UserTest {
@Autowired
private UserService userService;
@Test
public void test() {
userService.getName("zhangsan");
}
}
通过Java代码装配bean
优点:
可以实现基本数据类型的值、字符串字面量、类字面量等注入。
使用到的注解:
@Bean:默认情况下配置后bean的id和注解的方法名一样,可以通过name属性自定义id。
@ImportResourse:将指定的XML配置加载进来
@Import:将指定的Java配置加载进来。
注:不会用到@Component与@Autowired注解。
首先创建两个接口以及他们的实现类,不需要用@Component进行注解:
public interface UserDao {
public void save(String name);
}
public class UserDaoImpl implements UserDao {
@Override
public void save(String name) {
// TODO Auto-generated method stub
System.out.println("保存了数据:" + name);
}
}
public interface UserService {
public void getName(String name);
}
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void getName(String name) {
userDao.save(name);
}
}
配置类:
public class UserConfig {
@Bean
public UserService userService(UserDao userDao){
return new UserServiceImpl(userDao);
}
@Bean
public UserDao userDao(){
return new UserDaoImpl();
}
}
测试类:
@RunWith(SpringJUnit4ClassRunner.class)
//测试用,去指定类加载配置
@ContextConfiguration(classes = UserConfig.class)
public class UserTest {
@Autowired
private UserService userService;
@Test
public void test() {
userService.getName("zhangsan");
}
}
通过XML装配bean
优点:什么都能做。
缺点:配置繁琐。
使用到的标签:
<bean>:将类装配为bean,也可以导入java配置。属性id是为bean指定id,class是导入的类。
<constructor-arg>:构造器中声明DI,属性value是注入值,ref是注入对象引用。
spring的c-命名空间:起着和<constructor-arg>相似的作用。
<property>:设置属性,name是方法中参数名字,ref是注入的对象。
Spring的p-命名空间:起着和<property>相似的作用。
<import>:导入其他的XML配置。属性resource是导入XML配置的名称。
1、设值注入:即通过XML中配置bean的依赖类,通过层级property属性,来配置依赖关系,然后Spring通过setter方法,来实现依赖类的注入;
<property name="xxx" ref="xxx"></property>
2、构造器注入:方法同设值注入,不过具体实现的方法是通过显示的创造一个构造方法,构造方法的参数名称要与XML中配置的name名称一致,XML配置的标签为constructor-arg
<constructor-arg name="xxx" ref="xxx"></constructor-arg>
配置文件:
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 扫描路径 -->
<!-- <context:component-scan base-package="com.test"> </context:component-scan> -->
<bean id="userDao" class="com.test.UserDaoImpl"></bean>
<bean id="userService" class="com.test.UserServiceImpl">
<constructor-arg ref="userDao"/>
</bean>
</beans>
测试类:
public class MainTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("file:D:\\spring-dao.xml");
UserService userService = context.getBean(UserService.class);
userService.getName("zhangsan");
}
}
#混合使用三种装配:
1.在类上可以使用@ import(bbsConfig.class)组合其他java注解
2.在类上使用@ imortResource("classpath:spring-dao.xml")组合其他xml注解
3.在类上可以使用@ContenxtConfiguration包含class或者xml
4.在xml中可以用<import resource="spring-dao.xml">引入xml注解,也可以使用<bean class="com.bbs.dao.Userdao">引入java注解
参考文献:
https://www.cnblogs.com/maxshare/p/10467761.html
https://www.cnblogs.com/JimKing/p/8811119.html
https://blog.csdn.net/feng_zhiyu/article/details/81142850