关于spring:spring基础之三SpringIOC的注解应用

39次阅读

共计 10540 个字符,预计需要花费 27 分钟才能阅读完成。

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>{​}

正文完
 0