一、Spring基于注解的方式配置bean基本介绍和入门案例
1、基本介绍:
基于注解的方式配置bean,主要是项目开发中的组件,比如Action、Service、和Dao.
2、常用的组件注解的形式有:
@Component 表示当前注解标识的是一个组件。
@Controller表示当前注解标识的是一个控制器,通常用于Action类。
@Service表示当前注解标识的是一个处理业务逻辑的类,通常用于Service类。
@Repository表示当前注解标识的是一个持久化层的类,通常用于Dao类。
3、示例:
@Component //ioc容器扫描到这个注解,就会将Action构造一个bean。
public void Action() {
//....................
}
注意:1>写了注解就不用重复在bean.xml中去写<bean>..<bean/>了。
2>注解可以看做是自动配置bean,而不用手工在ioc bean配置文件中去配置,这是另外一种ioc创建bean的体系。 与前文spring手工配置bean 相比,这两种体系都可以独立管理bean,也可以相互补充。
3>@Component、@Controller、@Service、@Repository这四个注解对于IOC容器来说是同一个意思,ioc容器会扫描到写了某个注解的类,并构建一个bean 。 这四个注解只是为了程序员方便区分 某个类是Action、Service、Dao 中的哪一个。
4、需要引入spring-aop.RELEASE.jar
5、用法案例
1>创建一个类, 并写上注释
import org.springframework.stereotype.Component;
@Component
public class MyComponent {
}
2、在ioc容器bean.xml中去配置 spring自动扫描的包,包名不要写错!
<?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:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
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/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 打开ioc基于注解的配置-->
<!-- context:component-scan:表示启用ioc基于注解功能-->
<!-- base-package:com.itbull.ioc.component,-->
<!-- 表示我们去扫描com.itbul1.ioc.comgonent包的有注解的类.-->
<!-- 1.如果我们希望能够扫描 com.itbull.ioc.component 包的所有子包,-->
<!-- 则标准的写法是com.itbul1.ioc.component.*-->
<context:component-scan base-package="com.spring.component"/>
</beans>
3、在测试方法中,getBean() 。 用MyComponent.class, 当然还可以起别名, 后边会写到
@Test
public void test04() {
MyComponent myComponent = (MyComponent) applicationContext.getBean(MyComponent.class);
System.out.println(myComponent.getClass());
}
4、拿到了bean
6、自动扫描包的小结
细节说明:
1.必须在Spring配置文件中指定“自动扫描的包”,IOC容器才能够检测到当前项目中哪些类被标识了注解,注意到导入context名称空间
<-配置自动扫描的包-><context:component-scan base-package="com.itbull.ioc.component"/>可以使用通配符*方法的指定,比如com.itbull.ioc.* 表示更明确
2.Spring的IOC容器不能检测一个使用了@Controller注解的类到底是不是一个真正的控制器。注解的名称是用于程序员自己识别当前标识的是什么组件。其它的@Service@Repository也是一样的道理[也就是说spring的IOC容器只要检查到注解就会生成对象,但是这个注解的含义spring不会识别,注解是给程序员编程方便看的]
3.resource-pattern="User*.class"表示只扫描满足条件的.
<context:component-scan base-package="com.itbull.ioc.component" resource-pattern="User*.class"/> // 表示只扫描该包下名称以User打头的类
二、基于注解的方式配置bean-通过id获取
说明:
1.默认情况:标记注解后,类名首字母小写作为id的值。
2.可以使用注解的value属性指定id值,并且value可以省略。 (相当于bean id)
@Controller(value="userAction1")
@Controller("userAction1")
@Test
public void test04() {
MyComponent myComponent = (MyComponent) applicationContext.getBean("myent");
System.out.println(myComponent.getClass());
}
import org.springframework.stereotype.Component;
@Component(value = "myent")
public class MyComponent {
}
三、exclude-filter标签
说明 : exclude-filter标签是插在 <context:component->中使用的, 表示生成bean时排除掉某些注解的类
示例:
<context:component-scan base-package="com.spring.component">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
1、在beans.xml中配置排除过滤器,排除@Controler的类不扫描
<!--如何排除不希望扫描的哪些注解类,比如排除com.spring.component下面的@Controller类-->
<!-- 1.context:exclude-filter:表示排除哪些类不扫描-->
<!-- 2.type="annotation":表示根据注解的方式来排除-->
<!-- 3.expression="org.springframework.stereotype.Controller"要排除的注解的全类名-->
<context:component-scan base-package="com.spring.component">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
2、写注释,一个 写@Controler, 一个写@Repository
package com.spring.component;
import org.springframework.stereotype.Controller;
@Controller(value = "myent")
public class MyComponent {
}
package com.spring.component;
import org.springframework.stereotype.Repository;
@Repository(value = "baseDao")
public class BaseDao {
}
@Test
public void test04() {
BaseDao baseDao = (BaseDao) applicationContext.getBean("baseDao");
System.out.println(baseDao.getClass());
MyComponent myComponent = (MyComponent) applicationContext.getBean("myent");
System.out.println(myComponent.getClass());
}
4、可以看到@Repository被构建了bean, 而@Controler被排除了
细节:
<context:component-scan base-package="com.spring.component">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
其中type参数有五种类型,常用的两种,assignable表示过滤掉BaseXxx的子类
四、include-filter标签
include标签表示只扫描指定的注解的expression
<!--annotation-config="false":不再使用默认的扫描机制context:
include-filter:表示只是扫描指定的注解的类expression
="org.springframework.stereotype.Component":注解的全类名-->
<context:component-scan base-package="com.spring.component" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
package com.spring.component;
import org.springframework.stereotype.Controller;
@Controller(value = "myent")
public class MyComponent {
}
package com.spring.component;
import org.springframework.stereotype.Repository;
@Repository(value = "baseDao")
public class BaseDao {
}
@Test
public void test04() {
BaseDao baseDao = (BaseDao) applicationContext.getBean("baseDao");
System.out.println(baseDao.getClass());
MyComponent myComponent = (MyComponent) applicationContext.getBean("myent");
System.out.println(myComponent.getClass());
}
可以看到 写了注解@Respsitory的BaseDao被扫描到并构建了bean, 而 @Controller没有被扫描到
五、基于注解的自动装配
1、如果bean之间存在依赖, 那么如何使用注解实现自动装配(即ioc容器如何知道bean之间的关系)?
使用@Autowired
注意@Autowired的位置
package com.spring.component;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MyService {
private MyDao myDao;
public MyService() {
}
public MyService(MyDao myDao) {
this.myDao = myDao;
}
public MyDao getMyDao() {
return myDao;
}
public void setMyDao(MyDao myDao) {
this.myDao = myDao;
}
public void saveDao() {
System.out.println("save了一个对象");
}
}
六、spring的bean配置基于泛型依赖
在有泛型且有依赖的情况下,如何使用注解处理依赖
1、新建以下类
2、
package com.spring.myBean;
public class Book {
}
package com.spring.repository;
public abstract class BaseDao<T> {
public abstract void save();
}
import com.spring.myBean.Book;
import org.springframework.stereotype.Repository;
@Repository
public class BookDao extends BaseDao<Book>{
@Override
public void save() {
System.out.println("BookDao save");
}
}
package com.spring.service;
import com.spring.repository.BaseDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
public class BaseServic<T> {
@Autowired
private BaseDao<T> baseDao;
public void save () {
baseDao.save();
}
}
package com.spring.service;
import com.spring.myBean.Book;
import org.springframework.stereotype.Service;
@Service
public class BookService extends BaseServic<Book>{
}
@Test
public void test05() {
BookService bookService = (BookService) applicationContext.getBean(BookService.class);
bookService.save();
}
3、 总共五个类, 从BookService对象直接调用到了BookDao的save方法,其中包含了继承,泛型的关系。
4、代码执行过程简写:
首先BookService调用save方法, 然后jvm 先找到BookService对象,发现它继承了BaseService,又发现BaseService自动装配了BaseDao<T>, 带着泛型参数Book又找到BaseDao,但是发现BaseDao是一个抽象类,于是再去找实现了这个抽象类的BookDao, 最后找到了save()方法,发现需要构造BookDao对象,又发现BookDao已经被构造了, 于是直接调用save()方法