Spring框架的三种配置方式(二)---xml文件+注解

Spring框架有三种配置方式:

1.在spring2.5以前,用xml文件进行配置

2.在spring2.5以后,用xml文件注解(annotation)共同进行配置

3.在spring3.0以后,用注解(annotation)JavaConfig配置类进行配置

一、xml文件

见下一篇

二、xml文件+注解

        为什么要用注解+xml文件,而不直接用xml文件呢?因为过多的类注入和通过过多的set方法和构造方法来进行注入会导致代码冗余,所以我们可以通过注解+xml文件来优化代码,以下以一个具体的实例,通过注解+xml文件的方法来实现类的注入和基本数据的注入:

注入类

注入普通类

关键字:@Component

语法:@component(value="注入容器的id,如果省略,id自动默认是类名且首字母小写")

        使用@component进行类的注入代替了之前我们在xml文件中的:

<bean id="student" class="com.com.apesource.包.Student"></bean>

等价于: 注解+xml文件

注解:

@Component
Class Student{}

 xml文件:(含义:扫描所有被@Component注解所修饰的类,再将其注入容器)

<context:component-scan base-package="com.apesource"/>

注入数据访问层

关键字:@Repository

代替xml文件中的:

 <bean id="daoImp" class="com.apesource.dao.UserDaoImp"/>

注入业务层

关键字:@Service

代替xml文件中的

<bean id="serviceImp" class="com.apesource.service.UserServiceImp"/>

注入控制层

关键字:@Controller

代替xml文件中的

<bean id="controllerImp" class="com.apesource.controller.
UserControllerImp"/>

注入基本数据

@Value

使用方法

含义:注入基本数据

替换:<property><property/>

修饰:成员变量或对应的set方法

语法:(注解+xml文件)

1.注解:①@Value("数据内容")  、②@Value("动态获取数据内容") 

2.xml文件:

<context:property-placeholder location="message.properties" />
具体实现

1.学生类:

<1>//写法1:

@Component(value = "stu")
public class Student {
    //方法1:
    @Value("团团")
    private String stuName;
    @Value("180")
    private int stuHeight;
     @Override
    public String toString() {
        return "Student{" +
                "stuName='" + stuName + '\'' +
                ", stuHeight=" + stuHeight +
                '}';
    }
}

<2.1>//写法2:

@Component(value = "stu")
public class Student {
    //方法2:
   @Value("${msg1}")
    private String stuName;
    @Value("${msg2}")
    private int stuHeight;
     @Override
    public String toString() {
        return "Student{" +
                "stuName='" + stuName + '\'' +
                ", stuHeight=" + stuHeight +
                '}';
    }
}

<2.2> //message.properties文件:存放动态信息

msg1=毛毛
msg2=182

 2.xml文件

<?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.apsource"/>
<!--加载资源文件-->
<context:property-placeholder location="message.properties" />
</beans>

运行结果:

 

@AutoWried

使用方法

语法:@AutoWried(required="true-默认、false"),其中required代表是否必须进行装配

修饰对象:成员变量或对应的构造方法

含义:按照 通过set方法进行类型装配,set方法可以省略

具体实现

我们使用一个三层架构来说明他的具体实现:

1.//controller控制层

<1.1>IUserController接口:

public interface IUserController {
    public void save();
}

<1.2> UserControllerImp实现类

@Component(value="controller")
public class UserControllerImp implements IUserController{
    //向spring容器查找IUserService类型的对象实例
                                ,并通过构造方法注入给修饰的属性
    @Autowired
    IUserService service;
    //省略了set方法
    @Override
    public void save() {
        System.out.println("===controller的新增方法===");
        service.save();

    }
}   

2.dao数据访问层 

<2.1>IUserDao接口

public interface IUserDao {
    public void save();
}

 <2.2>UserDaoImp实现类

@Repository
public class UserDaoImp implements IUserDao{
    @Override
    public void save() {
        System.out.println("===dao的新增方法===");
    }
}

3.Service服务层

 <3.1>IUserService接口

public interface IUserService {
    public void save();
}

<3.2> UserServiceImp实现类

@Service
public class UserServiceImp  implements IUserService {
    @Autowired
    //@Autowired(required = false):如果找不到匹配的名字(dao),也不报错
    IUserDao dao;
    @Override
    public void save() {
        System.out.println("===service的新增方法===");
        dao.save();
    }
}

 4.测试类

public class Test {
    public static void main(String[] args) {
        ApplicationContext applicationContext=new 
             ClassPathXmlApplicationContext("applicationContext.xml");
        IUserController controller = (IUserController) applicationContext
                                          .getBean("controller");
        controller.save();

运行结果:

那当我们有两个UserDaoImp时@Autowired会为我们注入哪一个类呢?

 <2.3>UserDaoImp2

@Repository
public class UserDaoImp2 implements IUserDao{

    @Override
    public void save() {
        System.out.println("===dao2的新增方法===");

    }
}

 结果:

         为什么会出现这种错误呢?

        是因为@Autowired是先按类型进行匹配的,当我们没有UserDaoImp2时,dao层只有一个实现类类型是IUserDao,所以会直接匹配到UserDaoImp,输出:“===dao1的新增方法===”。那当我们新增了一个实现类UserDaoImp2时,dao层有两个实现类类型是IUserDao,那么此时就会按名称(dao)进行匹配,且两个实现类均没有起别名,默认名称为类名且首字母小写,分别为userDaoImp和userDaoImp2,没有叫dao的,所以会报“NoUniqueBeanDefinitionException”异常。

        那我们尝试给UserDaoImp2命名为dao,会发现输出为:

        可以总结为@Autowired先按类型匹配,再按名字匹配。当没有一个类型匹配时,会产生NoSuchBeanDefinitionException异常。

其他注解

@Primary

含义:首选项,当类型冲突的情况下,此注解修饰的类被列为首选(备胎扶正)

修饰:类

注意:不能单独使用,必须与@Component....联合使用

@Repository
public class UserDaoImp implements IUserDao{

    @Override
    public void save() {
        System.out.println("===dao1的新增方法===");
    }
}
@Repository
public class UserDaoImp2 implements IUserDao{

    @Override
    public void save() {
        System.out.println("===dao2的新增方法===");

    }
}

        此时两个dao层实现类均没有进行命名,按理来说应该出现NoUniqueBeanDefinitionException错误, 但是当我们给UserDaoImp写一个@Primary注解时,会优先匹配UserDaoImp类:

@Repository
@Primary
public class UserDaoImp implements IUserDao{

    @Override
    public void save() {
        System.out.println("===dao1的新增方法===");
    }
}

运行结果:

 

@Qualifier(value="名称")

含义:按照名称装配

修饰:成员变量

注意:不能单独使用,必须与@Autowired联合使用

@Service
public class UserServiceImp  implements IUserService {
    @Autowired
    @Qualifier(value = "userDaoImp")//按名称匹配userDaoImp
    IUserDao dao;

    @Override
    public void save() {
        System.out.println("===service的新增方法===");
        dao.save();
    }
}

结果:

 

@Resource(name="名称")

含义:按照名称装配

修饰:成员变量

注意:可以单独使用

这个注解和Qualifier作用相同,只不过Resource可以单独使用:

@Service
public class UserServiceImp  implements IUserService {
    @Resource(name="userDaoImp")
    IUserDao dao;

    @Override
    public void save() {
        System.out.println("===service的新增方法===");
        dao.save();
    }
}

结果:

@Scope

含义:配置类的作用域

修饰:类

注意:不能单独使用,必须与@Component....联合使用 @Scope("prototype") @Scope("singleton") @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)

@PostConstruct

初始化,修饰方法

@PreDestroy

销毁,修饰方法

三、注解+配置类

见下篇

  • 32
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值