从零到英雄:使用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"/>

注意:

  • 可以帮助我们识别@Antowired注解,但是不能帮我我们识别@Component@Controller@Service等这些注解。
    - 除了具有的功能之外,还具有自动将带有@component@service@Repository等注解的对象注册到spring容器中的功能。

IOC相关注解

@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(); //展示用户数据
    }
}

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}。

你可能感兴趣的:(Spring,spring,java)