从零到英雄:使用Spring打造强大的企业级应用-中
前言
Spring中bean有三种装配机制,分别是:
- 在xml中显式配置
 - 在java中显式配置
 - 隐式的bean发现机制和自动装配
 
自动化的装配bean。
Spring的自动装配需要从两个角度来实现,或者说是两个操作:
- 组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean;
 - 自动装配(autowiring):spring自动满足bean之间的依赖,也就是我们说的IoC/DI;
 
组件扫描和自动装配组合发挥巨大威力,使得显示的配置降低到最少。
推荐不使用自动装配xml配置 , 而使用注解
①byName
autowire byName (按名称自动装配)
<bean id="user" class="com.yu.pojo.User" autowire="byName">
   <property name="name" value="奇遇少年"/>
</bean>
②byType
<bean id="user" class="com.yu.pojo.User" autowire="byType">
   <property name="name" value="奇遇少年"/>
</bean>
注解开发
为了简化配置,Spring支持使用注解代替xml配置。jdk1.5开始支持注解,spring2.5开始全面支持注解。
Spring常用注解
注解开发准备工作
如果要使用注解开发必须要开启组件扫描,这样加了注解的类才会被识别出来。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"/>
注意:
<context:annotation-config/>可以帮助我们识别@Antowired注解,但是不能帮我我们识别@Component、@Controller、@Service等这些注解。
-<context:component-scan>除了具有<context:annotation-config />的功能之外,还具有自动将带有@component、@service、@Repository等注解的对象注册到spring容器中的功能。
IOC相关注解
@Component,@Controller,@Service ,@Repository 作用在类上
| 类 | 注解 | 
|---|---|
| Service类 | @Service | 
| Dao类 | @Repository | 
| Controller类 | @Controller | 
| 其他类 | @Component | 
例如:
配置
<?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 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(); //展示用户数据
    }
}
DI相关注解
如果一个bean已经放入Spring容器中了。那么我们可以使用下列注解实现属性注入,让Spring容器帮我们完成属性的赋值。
①@Value
主要用于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();
    }
}
②@AutoWired
Spring会给加了该注解的属性自动注入数据类型相同的对象。
- @Autowired是按类型自动转配的,不支持id匹配
 - 需要导入 spring-aop的包,之前导包已包含
 
@Service("userService")
public class UserDaoImpl implements UserService{
    @Autowired
    private UserDao userDao;
    ......
}
required属性代表这个属性是否是必须的,默认值为true。如果是true的话Spring容器中如果找不到相同类型的对象完成属性注入就会出现异常。
③@Qualifier
如果相同类型的bean在容器中有多个时,单独使用@AutoWired就不能满足要求,这时候可以再加上@Qualifier来指定bean的名字根据byName从容器中获取bean注入。
@Autowired
@Qualifier("userDao2")
private UserDao userDao;
注意:该直接不能单独使用。单独使用没有作用
④@Resource
- @Resource如有指定的name属性,先按该属性进行byName方式查找装配
 - 其次再进行默认的byName方式进行装配
 - 如果以上都不成功,则按byType的方式自动装配
 - 都不成功,则报异常
 
 //如果允许对象为null,设置required = false,默认为true
 @Resource(name = "userDao2")
private UserDao userDao;
结论:先进行byName查找,失败;再进行byType查找,成功。
⑤@scope
- singleton:默认的,Spring会采用单例模式创建这个对象。关闭工厂 ,所有的对象都会销毁。
 - prototype:多例模式。关闭工厂 ,所有的对象不会销毁。内部的垃圾回收机制会回收
 
@Controller("user")
@Scope("prototype")
public class User {
   @Value("奇遇少年")
   public String name;
}
xml配置文件相关注解
①@Configuration
标注在类上,表示当前类是一个配置类。我们可以用注解类来完全替换掉xml配置文件。
	注意:如果使用配置类替换了xml配置,spring容器要使用:AnnotationConfigApplicationContext
例如:
@Configuration
public class ApplicationContextConfig {
}
②@ComponentScan
可以用来代替context:component-scan标签来配置组件扫描。
basePackages属性来指定要扫描的包。
注意要加在配置类上。
@Configuration
@ComponentScan(basePackages = "com.yu")//指定要扫描的包
public class ApplicationContextConfig {
}
③@Bean
可以用来代替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);
    }
④@PropertySource
可以用来代替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}。
- 点赞
 - 收藏
 - 关注作者
 
            
           
评论(0)