Spring中bean有三种装配机制,分别是:
Spring的自动装配需要从两个角度来实现,或者说是两个操作:
组件扫描和自动装配组合发挥巨大威力,使得显示的配置降低到最少。
推荐不使用自动装配xml配置 , 而使用注解
autowire byName (按名称自动装配)
<bean id="user" class="com.yu.pojo.User" autowire="byName">
<property name="name" value="奇遇少年"/>
bean>
<bean id="user" class="com.yu.pojo.User" autowire="byType">
<property name="name" value="奇遇少年"/>
bean>
为了简化配置,Spring支持使用注解代替xml配置。jdk1.5开始支持注解,spring2.5开始全面支持注解。
如果要使用注解开发必须要开启组件扫描,这样加了注解的类才会被识别出来。Spring才能去解析其中的注解。
注解装配在 Spring 中是默认关闭的。所以需要在 Spring 文件中配置一下才能使用基于注解的装配 模式。
而自动装配就需要注解扫描,这里有两种开启注解扫描的方式,即
导包: xmlns:context="http://www.springframework.org/schema/context"
开启属性注解支持!
<context:annotation-config/>
和
导包:xmlns:context="http://www.springframework.org/schema/context"
<context:component-scan base-package="com.yu"/>
注意:
可以帮助我们识别@Antowired注
解,但是不能帮我我们识别@Component
、@Controller
、@Service等这些注解。
除了具有
的功能之外,还具有自动将带有@component
、@service
、@Repository
等注解的对象注册到spring容器中的功能。@Component,@Controller,@Service ,@Repository 作用在类上
类 | 注解 |
---|---|
Service类 | @Service |
Dao类 | @Repository |
Controller类 | @Controller |
其他类 | @Component |
例如:
配置
<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 https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.yu">context:component-scan>
beans>
接口和类
public interface UserDao {
public void showUser();
}
@Repository("userDao")
public class UserDaoImpl implements UserDao{
@Override
public void showUser() {
System.out.println("展示用户数据");
}
}
public interface UserService {
public void showUser();
}
@Service("userService")
public class UserDaoImpl implements UserService{
@Autowired
private UserDao userDao;
public void showUser() {
userDao.showUser();
}
}
测试
public class SpringTest {
public static void main(String[] args) {
//创建容器
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取对象
UserService userService = (UserService) app.getBean("userService");
userService.showUser(); //展示用户数据
}
}
如果一个bean已经放入Spring容器中了。那么我们可以使用下列注解实现属性注入,让Spring容器帮我们完成属性的赋值。
主要用于String,Integer等可以直接赋值的属性注入。不依赖setter方法,支持SpEL表达式。
@Service("userService")
public class UserDaoImpl implements UserService{
@Autowired
private UserDao userDao;
@Value("666")
private int total;
@Value("奇遇少年")
private String name;
@Value("#{22+1}")
private Integer age;
public void showUser() {
System.err.println(total+name+age);
userDao.showUser();
}
}
Spring会给加了该注解的属性自动注入数据类型相同的对象。
@Service("userService")
public class UserDaoImpl implements UserService{
@Autowired
private UserDao userDao;
......
}
required
属性代表这个属性是否是必须
的,默认值为true
。如果是true
的话Spring容器中如果找不到
相同类型的对象完成属性注入就会出现异常
。
如果相同类型
的bean在容器中有多个
时,单独使用@AutoWired就不能满足要求,这时候可以再加上@Qualifier
来指定bean的名字
根据byName从容器中获取bean注入。
@Autowired
@Qualifier("userDao2")
private UserDao userDao;
注意:该直接不能单独使用。单独使用没有作用
//如果允许对象为null,设置required = false,默认为true
@Resource(name = "userDao2")
private UserDao userDao;
结论:先进行byName查找,失败;再进行byType查找,成功。
@Controller("user")
@Scope("prototype")
public class User {
@Value("奇遇少年")
public String name;
}
标注在类上,表示当前类是一个配置类。我们可以用注解类来完全替换掉xml配置文件。
注意:如果使用配置类替换了xml配置,spring容器要使用:AnnotationConfigApplicationContext
例如:
@Configuration
public class ApplicationContextConfig {
}
可以用来代替context:component-scan标签来配置组件扫描。
basePackages属性来指定要扫描的包。
注意要加在配置类上。
@Configuration
@ComponentScan(basePackages = "com.yu")//指定要扫描的包
public class ApplicationContextConfig {
}
可以用来代替bean标签,主要用于第三方类的注入。
使用:定义一个方法,在方法中创建对应的对象并且作为返回值返回。然后在方法上加上@Bean注解,注解的value属性来设置bean的名称。
例如:
@Configuration
@ComponentScan(basePackages = "com.yu")
public class ApplicationContextConfig {
@Bean("dataSource")//bean的名称dataSource
public DruidDataSource getDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUrl("jdbc:mysql://localhost:3306/spring_db");
druidDataSource.setUsername("root");
druidDataSource.setPassword("root");
return druidDataSource;
}
}
注意事项:如果同一种类型的对象在容器中只有一个,我们可以不设置bean的名称。
获取方式如下:
public static void main(String[] args) {
//创建注解容器
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(ApplicationContextConfig .class);
//根据对应类的字节码对象获取
DataSource bean = app.getBean(DataSource.class);
System.out.println(userService);
}
可以用来代替context:property-placeholder,让Spring读取指定的properties文件。然后可以使用@Value来获取读取到的值。
使用:在配置类上加@PropertySource注解,注解的value属性来设置properties文件的路径。
然后在配置类中定义成员变量。在成员变量上使用@Value注解来获取读到的值并给对应的成员变量赋值。
例如:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db
jdbc.username=root
jdbc.password=root
读取文件并且获取值
@Configuration
@ComponentScan(basePackages = "com.yu")
@PropertySource("jdbc.properties")
public class ApplicationContextConfig {
@Value("${jdbc.driver}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean
public DruidDataSource getDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(driverClassName);
druidDataSource.setUsername(username);
druidDataSource.setUrl(url);
druidDataSource.setPassword(password);
return druidDataSource;
}
}
注意事项:使用@Value获取读到的properties文件中的值时使用的是${key},而不是#{key}。