Spring四个注解
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.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--
实验15:通过注解分别创建Dao、Service、Controller
通过给bean上添加某些注解,可以快速将bean加入到IOC容器中
某个类上添加上任何一个注解都能快速将这个组件加入到IOC容器的管理中;
Spring有四个注解:控制器;
@Controller:控制器,我们推荐给控制层(servlet包下的这些)的组件加这个注解
@Service:业务逻辑,我们推荐业逻辑层的组件添加这个注解:BookService
@Repository:给数据库层(持久化层,dao层)的组件添加这个注解
@Component:给不属于以上几层的组件添加这个注解;
注解可以随便加,Spring不会去验证你的这个组件。
是否如你注解所说就是一个dao的或者就是一个servlet层的组件;
我们推荐各自层加各自注解,方便程序员看
使用注解将组件快速的加入容器中的步骤:
1)给要添加的组件上标四个注解中的任何一个
2)告诉Spring,自动扫描加了注解的组件,依赖context名称空间
3)一定要导入aop包:支持加注解模式的
-->
<!-- context:component-scan:自动组件扫描
base-package:指定扫描的基础包,把基础包及他下面所有的包的所有加了注解的类,
自动扫描进入IOC容器中-->
<context:component-scan base-package="com.czl"></context:component-scan>
<!-- 注解和bean配置相结合,因为不是所有的类都可以用注解,如jdk下的类加入容器中,
就只能自己用bean添加进去-->
测试类
public class IOCTest {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
/**
* 使用注解加入到容器中的组件,和使用配置加入到容器中的组件行为都是默认的一样的。
* 1、组件的id默认就是组件的类名首字母小写
* @Repository("bookdaoHaha)//修改id
* public class bookDao(){}
*
* 2、组件的作用域:默认就是单例的
* @Scope(value = "prototype")//修改作用域
*/
@Test
public void test01(){
Object bookDao = ioc.getBean("bookDao");
Object bookDao1 = ioc.getBean("bookDao");
System.out.println(bookDao == bookDao1);//true
}
}
指定扫描包时的选择
<!--实验17:使用context:exclude-filter指定扫描包时不包含的类-->
<!--扫描的时候可以排除一些不要的组件-->
<!--
【type="annotation"】:指定排除规则,按照注解进行排除。标注了指定注解的不要
【type="assignable"】:指定排除某个具体的类,按照类排除
type="aspectj"
type="custom"
type="regex"
expression="":注解的全类名-->
<!-- <context:component-scan base-package="com.czl">-->
<!-- <context:exclude-filter type="assignable" expression="com.czl.service.BookService"/>-->
<!--<!– <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>–>-->
<!-- </context:component-scan>-->
<!-- 实验16:使用context:include-filter指定扫描包时要包含的类
只扫描进入那些组件,默认都是全部扫描进来
一定要禁用掉默认的过滤规则 use-default-filters="false"
-->
<!-- <context:component-scan base-package="com.czl" use-default-filters="false">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>-->
使用@Autowired注解实现根据类型实现自动装配★
@Autowired知识点
<!--DI(依赖注入)-->
<!--实验18:使用@Autowired注解实现根据类型实现自动装配★-->
<context:component-scan base-package="com.czl"></context:component-scan>
<!-- @Autowired原理:默认根据@Autowired注解标记的成员变量名作为id查找bean,进行装配★
@Autowired
private BookService bookService;
1)先按类型去容器中找到对应的组件:bookService = ioc.getBean("BookService.class");
1)找到一个:找到就赋值
2)没有找到:抛异常
3)找到多个?装配上?
1)按照变量名作为id继续匹配;BookService(bookService)、BookServiceExt(bookServiceExt)
@Autowired
private BookService bookServiceExt2;//用id进行匹配没有匹配上
1)匹配上:装配
2)没有匹配上?报错
原因:因为我们按照变量名作为id进行匹配的
使用@Qualifier("bookServiceExt")指定一个新的字符串作为id
1)找到:装配
2)找不到:报错;
发现Autowired标注的自动装配的默认属性是一定装配上的;这个时候可以修改@Autowired的属性required
找到就装配,找不到就拉倒 @Autowired(required=false)这样子不会报錯了
-->
<!-- 实验19:如果资源类型的bean不止一个,
默认根据@Autowired注解标记的成员变量名作为id查找bean,进行装配★
实验20:如果根据成员变量名作为id还是找不到bean,
可以使用@Qualifier注解明确指定目标bean的id★
实验21:在方法的形参位置使用@Qualifier注解
实验22:@Autowired注解的required属性指定某个属性允许不被设置
-->
<!-- @Autowired @Resource @Inject; 都是自动装配的意思
@Autowired:最强大:Spring自己的注解
@Resource: j2ee中的,java的标准
@Resource:扩展性更强;因为是java的标准 若切换成另外一个容器框架(所幸整个
容器框架抛开EJB不说,容器框架只有SPring一家,没有别家在做这个事),
@Resource还是可以使用的,@Autowired就不行了
-->
<!-- 总结:使用@Autowired在方法或者变量前面,该类要在ioc容器的管理下,IOC容器扫描
包并且初始化创建对象的的时候,如果看到该类有这些@Autowired的方法或者变量,会一并初始化配置-->
</beans>
demo
/**
* id 默认是类名首字母小写
*/
//@Repository("bookDaohhh")修改名字、
@Repository
//@Scope(value = "prototype")
public class BookDao {
public void saveBook(){
System.out.println("图书已经保存。。。");
}
}
@Service
public class BookService {
// @Autowired
@Resource
private BookDao bookDao;
public void save(){
System.out.println("bookService正在调用dao帮你保存图书..");
bookDao.saveBook();
}
}
/
**
* 属性的自动注入
* @Autowired:Spring会自动为这个属性赋值;
* 一定是去容器中找到这个属性对应的组件
*/
@Controller
public class BookServlet {
@Autowired
private BookService bookService;
public void doGet(){
bookService.save();
}
}
@Test
public void test02(){
BookServlet bean = ioc.getBean(BookServlet.class);
bean.doGet();//bookService正在调用dao帮你保存图书.. 图书已经保存。。。
}
多添加一个BookService
@Service
public class BookServiceExt extends BookService {//父类是BooService,因此组件类型是BookService
@Autowired
private BookDao bookDao;
@Override
public void save(){
System.out.println("bookServiceExt......");
}
}
IOC有两个BookService后的Servlet层的@Autowired的赋值
package com.czl.servlet;
import com.czl.dao.BookDao;
import com.czl.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
/**
* 属性的自动注入
* @Autowired:Spring会自动为这个属性赋值;
* 一定是去容器中找到这个属性对应的组件
*/
@Controller
public class BookServlet {
/*@Autowired
自动装配,自动为这个属性赋值
由于有BookService和BookServiceExt两个类,而且BookServiceExt本质上也是BookService组件
且都配置到IOC容器中了,也就是IOC容器中配置了两个BookService,默认id为bookService和bookServiceExt
默认根据@Autowired注解标记的成员变量名作为id查找bean,进行装配★,此时装配到的就是BookServiceExt了
代码:
@Autowired
// private BookService bookService;
private BookService bookServiceExt;
public void doGet(){
bookServiceExt.save();
}
*/
//自动装配,自动为这个属性赋值
//Qualifier:指定一个名作为id,然后Autowired去IOC容器中自动匹配赋值,让Spring别使用变量名作为id,
@Qualifier("bookService")
@Autowired
private BookService bookServiceExt2;
public void doGet(){
bookServiceExt2.save();
}
/* @Qualifier("bookServicehaha")
@Autowired(required = false)
private BookService bookServiceExt2;
public void doGet(){
System.out.println(bookServiceExt2);
}*/
/**
* 方法上有@Autowired的话
* 1)这个方法也会在bean创建的时候自动运行
* 2)这个方法上的每一个参数都会自动注入值(只对引用类型有用)
* (注入方式先按类型装配,若按照类型找到多个则按变量名作为id装配,而且@Qualifier可以写在参数上)
*
*/
@Autowired
public void hahaha(BookDao bookDao,@Qualifier("bookServiceExt") BookService bookService){
System.out.println("Spring运行 这个方法..."+bookDao+"-->"+ bookService);
}//在bean创建的时候就会自动注入该方法并且把引用类型的值填充进去
}
Spring的单元测试
/**
* 使用Spring的单元测试:
* 1、导包:Spring单元测试包Spring-test-4.0.0.RELEASE.jar
* 2、@ContextConfiguration(locations="")使用它来指定Spring配置文件的位置
* 3、@RunWith指定用哪种驱动进行单元测试,默认就是junit org.junit.runner
* @RunWith(SpringJUnit4ClassRunner.class)使用Spring的单元测试模块来执行标了
* @Test注解的测试方法
* 以前@Test注解只是由Junit执行
* 好处:我们不用ioc.getBean()获取组件了,直接Autowired组件。Spring为我们自动装配
*
*
*/
@ContextConfiguration(locations = "classpath:applicationContext.xml")//classpath表示类路径下
@RunWith(SpringJUnit4ClassRunner.class)
public class IOCTest02 {
// ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
@Autowired
BookServlet bookServlet;
@Test
//Spring的单元驱动执行此Test方法时,Spring按照ContextConfiguration指定的配置文件的位置创建出ioc容器对象
// 此时@Autowired注入什么,spring就会自动注入什么
public void test01(){
System.out.println(bookServlet);
// System.out.println(ioc);
}
}