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.java
package com.mashibing.controller;
import org.springframework.stereotype.Controller;
@Controller
public class PersonController {public PersonController() {System.out.println("创建对象");
}
}
PersonService.java
package com.mashibing.service;
import org.springframework.stereotype.Service;
@Service
public class PersonService {
}
PersonDao.java
package 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.java
package com.mashibing.controller;
import com.mashibing.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class PersonController {
@Autowired
private PersonService personService;
public PersonController() {System.out.println("创建对象");
}
public void getPerson(){personService.getPerson();
}
}
PersonService.java
package com.mashibing.service;
import com.mashibing.dao.PersonDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class PersonService {
@Autowired
private PersonDao personDao;
public void getPerson(){personDao.getPerson();
}
}
PersonDao.java
package com.mashibing.dao;
import org.springframework.stereotype.Repository;
@Repository
public class PersonDao {
public void getPerson(){System.out.println("PersonDao:getPerson");
}
}
留神:当应用 AutoWired 注解的时候,主动拆卸的时候是依据类型实现的。
1、如果只找到一个,则间接进行赋值,
2、如果没有找到,则间接抛出异样,
3、如果找到多个,那么会依照变量名作为 id 持续匹配,
1、匹配上间接进行拆卸
2、如果匹配不上则间接报异样
PersonServiceExt.java
package com.mashibing.service;
import com.mashibing.dao.PersonDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class PersonServiceExt extends PersonService{
@Autowired
private PersonDao personDao;
public void getPerson(){System.out.println("PersonServiceExt......");
personDao.getPerson();}
}
PersonController.java
package com.mashibing.controller;
import com.mashibing.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class PersonController {
@Autowired
private PersonService personServiceExt;
public PersonController() {System.out.println("创建对象");
}
public void getPerson(){personServiceExt.getPerson();
}
}
还能够应用 @Qualifier 注解来指定 id 的名称,让 spring 不要应用变量名, 当应用 @Qualifier 注解的时候也会有两种状况:
1、找到,则间接拆卸
2、找不到,就会报错
PersonController.java
package 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;
@Controller
public class PersonController {
@Autowired
@Qualifier("personService")
private PersonService personServiceExt2;
public PersonController() {System.out.println("创建对象");
}
public void getPerson(){personServiceExt2.getPerson();
}
}
通过上述的代码咱们可能发现,应用 @AutoWired 必定是可能拆卸上的,如果拆卸不上就会报错。
4、@AutoWired 能够进行定义在办法上
当咱们查看 @AutoWired 注解的源码的时候发现,此注解不仅能够应用在成员变量上,也能够应用在办法上。
PersonController.java
package 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;
@Controller
public 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.java
package 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;
@Controller
public 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.java
package com.mashibing.bean;
public class Student {
}
Teacher.java
package com.mashibing.bean;
public class Teacher {
}
BaseDao.java
package com.mashibing.dao;
import org.springframework.stereotype.Repository;
@Repository
public abstract class BaseDao<T> {
public abstract void save();}
StudentDao.java
package com.mashibing.dao;
import com.mashibing.bean.Student;
import org.springframework.stereotype.Repository;
@Repository
public class StudentDao extends BaseDao<Student>{public void save() {System.out.println("保留学生");
}
}
TeacherDao.java
package com.mashibing.dao;
import com.mashibing.bean.Teacher;
import org.springframework.stereotype.Repository;
@Repository
public class TeacherDao extends BaseDao<Teacher> {public void save() {System.out.println("保留老师");
}
}
StudentService.java
package com.mashibing.service;
import com.mashibing.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class StudentService {
@Autowired
private StudentDao studentDao;
public void save(){studentDao.save();
}
}
TeacherService.java
package com.mashibing.service;
import com.mashibing.dao.TeacherDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class TeacherService {
@Autowired
private TeacherDao teacherDao;
public void save(){teacherDao.save();
}
}
MyTest.java
import 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.java
package 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.java
package 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;
@Service
public class StudentService extends BaseService<Student> {}
TeacherService.java
package 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;
@Service
public class TeacherService extends BaseService<Teacher>{}