SpringIOC的注解利用

在之前的我的项目中,咱们都是通过xml文件进行bean或者某些属性的赋值,其实还有另外一种注解的形式,在企业开发中应用的很多,在bean上增加注解,能够疾速的将bean注册到ioc容器。

1、应用注解的形式注册bean到IOC容器中

applicationContext.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.or...
http://www.springframework.or...
http://www.springframework.or...">

<!--
如果想要将自定义的bean对象增加到IOC容器中,须要在类上增加某些注解
Spring中蕴含4个次要的组件增加注解:
@Controller:控制器,举荐给controller层增加此注解
@Service:业务逻辑,举荐给业务逻辑层增加此注解
@Repository:仓库治理,举荐给数据拜访层增加此注解
@Component:给不属于以上基层的组件增加此注解
留神:咱们尽管人为的给不同的层增加不同的注解,然而在spring看来,能够在任意层增加任意注解
spring底层是不会给具体的档次验证注解,这样写的目标只是为了进步可读性,最偷懒的形式
就是给所有想交由IOC容器治理的bean对象增加component注解

应用注解须要如下步骤:
1、增加上述四个注解中的任意一个
2、增加主动扫描注解的组件,此操作须要依赖context命名空间
3、增加主动扫描的标签context:component-scan

留神:当应用注解注册组件和应用配置文件注册组件是一样的,然而要留神:
1、组件的id默认就是组件的类名首字符小写,如果非要改名字的话,间接在注解中增加即可
2、组件默认状况下都是单例的,如果须要配置多例模式的话,能够在注解下增加@Scope注解
-->
<!--
定义主动扫描的根底包:
base-package:指定扫描的根底包,spring在启动的时候会将根底包及子包下所有加了注解的类都主动
扫描进IOC容器
-->
<context:component-scan base-package="com.mashibing"></context:component-scan>
</beans>

PersonController.javapackage com.mashibing.controller;import org.springframework.stereotype.Controller;@Controllerpublic class PersonController { public PersonController() { System.out.println("创建对象"); }}PersonService.javapackage com.mashibing.service;import org.springframework.stereotype.Service;@Servicepublic class PersonService {}PersonDao.javapackage com.mashibing.dao;import org.springframework.stereotype.Repository;@Repository("personDao")@Scope(value="prototype")public class PersonDao {}

2、定义扫描包时要蕴含的类和不要蕴含的类

当定义好根底的扫描包后,在某些状况下可能要有选择性的配置是否要注册bean到IOC容器中,此时能够通过如下的形式进行配置。

applicationContext.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.or...
http://www.springframework.or...
http://www.springframework.or...">
<context:component-scan base-package="com.mashibing" use-default-filters="false">
<!--
当定义好根底扫描的包之后,能够排除包中的某些类,应用如下的形式:
type:示意指定过滤的规定
annotation:依照注解进行排除,标注了指定注解的组件不要,expression示意要过滤的注解
assignable:指定排除某个具体的类,依照类排除,expression示意不注册的具体类名
aspectj:前面讲aop的时候阐明要应用的aspectj表达式,不必
custom:定义一个typeFilter,本人写代码决定哪些类被过滤掉,不必
regex:应用正则表达式过滤,不必
-->
<!--       <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>-->

<!--指定只扫描哪些组件,默认状况下是全副扫描的,所以此时要配置的话须要在component-scan标签中增加 use-default-filters="false"-->
<context:include-filter type="assignable" expression="com.mashibing.service.PersonService"/>
</context:component-scan>
</beans>

3、应用@AutoWired进行主动注入

应用注解的形式实现主动注入须要应用@AutoWired注解。

PersonController.javapackage com.mashibing.controller;import com.mashibing.service.PersonService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;@Controllerpublic class PersonController { @Autowired private PersonService personService; public PersonController() { System.out.println("创建对象"); } public void getPerson(){ personService.getPerson(); }}PersonService.javapackage com.mashibing.service;import com.mashibing.dao.PersonDao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class PersonService { @Autowired private PersonDao personDao; public void getPerson(){ personDao.getPerson(); }}PersonDao.javapackage com.mashibing.dao; import org.springframework.stereotype.Repository;@Repositorypublic class PersonDao { public void getPerson(){ System.out.println("PersonDao:getPerson"); }}

留神:当应用AutoWired注解的时候,主动拆卸的时候是依据类型实现的。

1、如果只找到一个,则间接进行赋值,

2、如果没有找到,则间接抛出异样,

3、如果找到多个,那么会依照变量名作为id持续匹配,

1、匹配上间接进行拆卸

2、如果匹配不上则间接报异样

PersonServiceExt.javapackage com.mashibing.service;import com.mashibing.dao.PersonDao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class PersonServiceExt extends PersonService{ @Autowired private PersonDao personDao; public void getPerson(){ System.out.println("PersonServiceExt......"); personDao.getPerson(); }}PersonController.javapackage com.mashibing.controller;import com.mashibing.service.PersonService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;@Controllerpublic class PersonController { @Autowired private PersonService personServiceExt; public PersonController() { System.out.println("创建对象"); } public void getPerson(){ personServiceExt.getPerson(); }}

还能够应用@Qualifier注解来指定id的名称,让spring不要应用变量名,当应用@Qualifier注解的时候也会有两种状况:

1、找到,则间接拆卸

2、找不到,就会报错

PersonController.javapackage com.mashibing.controller;import com.mashibing.service.PersonService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Controller;@Controllerpublic class PersonController { @Autowired @Qualifier("personService") private PersonService personServiceExt2; public PersonController() { System.out.println("创建对象"); } public void getPerson(){ personServiceExt2.getPerson(); }}

通过上述的代码咱们可能发现,应用@AutoWired必定是可能拆卸上的,如果拆卸不上就会报错。

4、@AutoWired能够进行定义在办法上

当咱们查看@AutoWired注解的源码的时候发现,此注解不仅能够应用在成员变量上,也能够应用在办法上。

PersonController.javapackage com.mashibing.controller;import com.mashibing.dao.PersonDao;import com.mashibing.service.PersonService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Controller;@Controllerpublic class PersonController { @Qualifier("personService") @Autowired private PersonService personServiceExt2; public PersonController() { System.out.println("创建对象"); } public void getPerson(){ System.out.println("personController..."+personServiceExt2);//        personServiceExt2.getPerson(); } /** * 当办法上有@AutoWired注解时: *  1、此办法在bean创立的时候会主动调用 *  2、这个办法的每一个参数都会主动注入值 * @param personDao */ @Autowired public void test(PersonDao personDao){ System.out.println("此办法被调用:"+personDao); }  /** * @Qualifier注解也能够作用在属性上,用来被当作id去匹配容器中的对象,如果没有 * 此注解,那么间接依照类型进行匹配 * @param personService */ @Autowired public void test2(@Qualifier("personServiceExt") PersonService personService){ System.out.println("此办法被调用:"+personService); }}

5、主动拆卸的注解@AutoWired,@Resource

在应用主动拆卸的时候,出了能够应用@AutoWired注解之外,还能够应用@Resource注解,大家须要晓得这两个注解的区别。

1、@AutoWired:是spring中提供的注解,@Resource:是jdk中定义的注解,依附的是java的规范

2、@AutoWired默认是依照类型进行拆卸,默认状况下要求依赖的对象必须存在,@Resource默认是依照名字进行匹配的,同时能够指定name属性。

3、@AutoWired只适宜spring框架,而@Resource扩展性更好

PersonController.javapackage com.mashibing.controller;import com.mashibing.dao.PersonDao;import com.mashibing.service.PersonService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Controller;import javax.annotation.Resource;@Controllerpublic class PersonController { @Qualifier("personService") @Resource private PersonService personServiceExt2; public PersonController() { System.out.println("创建对象"); } public void getPerson(){ System.out.println("personController..."+personServiceExt2); personServiceExt2.getPerson(); } /** * 当办法上有@AutoWired注解时: *  1、此办法在bean创立的时候会主动调用 *  2、这个办法的每一个参数都会主动注入值 * @param personDao */ @Autowired public void test(PersonDao personDao){ System.out.println("此办法被调用:"+personDao); } /** * @Qualifier注解也能够作用在属性上,用来被当作id去匹配容器中的对象,如果没有 * 此注解,那么间接依照类型进行匹配 * @param personService */ @Autowired public void test2(@Qualifier("personServiceExt") PersonService personService){ System.out.println("此办法被调用:"+personService); }}

6、泛型依赖注入

为了解说泛型依赖注入,首先咱们须要先写一个根本的案例,依照咱们之前学习的常识:

Student.javapackage com.mashibing.bean;public class Student {}Teacher.javapackage com.mashibing.bean;public class Teacher {}BaseDao.javapackage com.mashibing.dao;import org.springframework.stereotype.Repository;@Repositorypublic abstract class BaseDao<T> { public abstract void save();}StudentDao.javapackage com.mashibing.dao;import com.mashibing.bean.Student;import org.springframework.stereotype.Repository;@Repositorypublic class StudentDao extends BaseDao<Student>{ public void save() { System.out.println("保留学生"); }}TeacherDao.javapackage com.mashibing.dao;import com.mashibing.bean.Teacher;import org.springframework.stereotype.Repository;@Repositorypublic class TeacherDao extends BaseDao<Teacher> { public void save() { System.out.println("保留老师"); }}StudentService.javapackage com.mashibing.service;import com.mashibing.dao.StudentDao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class StudentService { @Autowired private StudentDao studentDao; public void save(){ studentDao.save(); }}TeacherService.javapackage com.mashibing.service;import com.mashibing.dao.TeacherDao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class TeacherService { @Autowired private TeacherDao teacherDao; public void save(){ teacherDao.save(); }}MyTest.javaimport com.mashibing.service.StudentService;import com.mashibing.service.TeacherService;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import javax.sql.DataSource;import java.sql.SQLException;public class MyTest { public static void main(String[] args) throws SQLException { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); StudentService studentService = context.getBean("studentService",StudentService.class); studentService.save(); TeacherService teacherService = context.getBean("teacherService",TeacherService.class); teacherService.save(); }}

上述代码是咱们之前的能够实现的性能,然而能够思考,Service层的代码是否可能改写:

BaseService.javapackage com.mashibing.service;import com.mashibing.dao.BaseDao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;public class BaseService<T> {  @Autowired BaseDao<T> baseDao;  public void save(){ System.out.println("主动注入的对象:"+baseDao); baseDao.save(); }}StudentService.javapackage com.mashibing.service;import com.mashibing.bean.Student;import com.mashibing.dao.StudentDao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class StudentService extends BaseService<Student> {}TeacherService.javapackage com.mashibing.service;import com.mashibing.bean.Teacher;import com.mashibing.dao.TeacherDao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class TeacherService extends BaseService<Teacher>{}