使用java注解的方式去实现IOC的配置
主要目标:
- 1.学习spring基于java注解的配置方式
- 2.熟悉spring配置注解
进行环境搭建
- 1.创建maven项目
- 2.引入spring依赖包
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
- 3.创建spring-ioc.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
- 4.创建数据库配置文件db.properties
mysql.username=mall
mysql.password=mall
mysql.url=jdbc:mysql://192.168.1.150:3306/mall
mysql.driver=com.mysql.jdbc.Driver
- 5.创建接口和类
com.learn.controller
UserController
com.learn.service
IUserService
com.learn.service.impl
UserServiceImpl
com.learn.dao
IUserDao
com.learn.dao.impl
UserDaoImpl
com.learn.bean
User
Role
开始学习基础内容
- 1.对类进行注解标注,将bean注册到容器中有4种方式:
1.使用xml进行配置bean标签
2.使用@Component以及相关的标签进行注解后,使用包扫描方式进行注册
3.使用@Bean注解
4.使用@Import注解
本例主要使用@Component方式进行注册bean
@Component,@Controller,@Service,@Repository 四个注解性质基本相同具体如下:
@Component
@Component:spring 注册组件的注解,@Service,@Controller,@Repository等的注册功能都是由该注解提供,使用该标注后对应类将注册到容器中
源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
String value() default "";
}
@Controller
@Controller:控制器,推荐给controller层添加此注解
源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
@AliasFor(annotation = Component.class)
String value() default "";
}
@Service
@Service:业务逻辑,推荐给业务逻辑层添加此注解
源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
@AliasFor(annotation = Component.class)
String value() default "";
}
@Repository
@Repository:仓库管理,推荐给数据访问层添加此注解
源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
@AliasFor(annotation = Component.class)
String value() default "";
}
从源码上看@Controller,@Service,@Repository的源码没有区别,只是名称定义不同,实现功能上三者完全一致,只是表示不同意义,方便开发者更直观的定义各个类的意义.
并且能对不同类型的bean进行一个区别,方便进行操作.
2.给各个类加上@Component相关注解
Controller类加上@Controller注解
例如:
@Controller//将组建添加到容器中--标注为控制器
public class UserController
ServiceImpl相关的类均加上@Service注解
例如:
@Service//配置对象加载到容器中--标注为业务逻辑类
public class UserServiceImpl implements IUserService
给DaoImpl相关类加上@Repository注解
@Repository//配置对象加载到容器中--标注为数据访问
public class UserDaoImpl implements IUserDao{
给其他需要注册的类加上@Component注解
例如
@Component
public class User
3.在spring-ioc.xml文件中进行包扫描相关配置,将指定包内的被我们标注要注册的类均注册到spring容器中
示例:
<context:component-scan base-package="com.learn" >
</context:component-scan>
//base-package为指定的包路径
context:component-scan标签
包含2个子标签,7个属性
各个标签和属性的意义示例:
<context:component-scan base-package="com.wjx.betalot" <!-- 扫描的基本包路径 -->
annotation-config="true" <!-- 是否激活属性注入注解 -->
name-generator="org.springframework.context.annotation.AnnotationBeanNameGenerator" <!-- Bean的ID策略生成器 -->
resource-pattern="**/*.class" <!-- 对资源进行筛选的正则表达式,这边是个大的范畴,具体细分在include-filter与exclude-filter中进行 -->
scope-resolver="org.springframework.context.annotation.AnnotationScopeMetadataResolver" <!-- scope解析器 ,与scoped-proxy只能同时配置一个 -->
scoped-proxy="no" <!-- scope代理,与scope-resolver只能同时配置一个 -->
use-default-filters="false" <!-- 是否使用默认的过滤器,默认值true -->
>
<!-- 注意:若使用include-filter去定制扫描内容,要在use-default-filters="false"的情况下,不然会“失效”,被默认的过滤机制所覆盖 -->
<!-- annotation是对注解进行扫描 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
<!-- assignable是对类或接口进行扫描 -->
<context:include-filter type="assignable" expression="com.wjx.betalot.performer.Performer"/>
<context:include-filter type="assignable" expression="com.wjx.betalot.performer.impl.Sonnet"/>
<!-- 注意:在use-default-filters="false"的情况下,exclude-filter是针对include-filter里的内容进行排除 -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="assignable" expression="com.wjx.betalot.performer.impl.RainPoem"/>
<context:exclude-filter type="regex" expression=".service.*"/>
</context:component-scan>
<context:exclude-filter>和<context:include-filter>两个标签的tyep类型决定加载与排除的规则,具体type类型有如下几种
/*
annotation:按照注解进行排除,标注了指定注解的组件不要,expression表示要过滤
的注解
assignable:指定排除某个具体的类,按照类排除,expression表示不注册的具体类名
aspectj:后面讲aop的时候说明要使用的aspectj表达式
custom:定义一个typeFilter,自己写代码决定哪些类被过滤掉
regex:使用正则表达式过滤
*/
参考链接https://www.cnblogs.com/fightingcoding/p/component-scan.html
4.完成包扫描后可以使用自动注入来获取bean实例
自动注入实现有两个标签分别是
@Autowired
@Resource
@Autowired标签的使用
使用@Autowired来实现自动注入
·默认优先根据类型去匹配
·如果匹配到多个类型则会按照名字匹配
·如果名又没有匹配到则会报错:
1.可以去修改属性的名字对应bean的名字:userServiceImpl
2.可以去修改Bean的名字对应属性的名字:@Service("userService")
3.可以通过@Qualifier设置属性的名字(覆盖) :@Qualifier("userServiceImpl")
4.可以通过@Primary 设置其中一个Bean为主要的自动注入Bean:@Primary
5.使用泛型作为自动注入限定符
注意:
- 如果只找到一个,则直接进行赋值
- 如果没有找到,则直接抛出异常
- 如果找到多个,那么会按照变量名作为id继续匹配
- 匹配上直接进行装配
- 如果匹配不上则直接报异常
- 当定义@Autowired的required为false时,没有匹配上是不会报错的,默认为ture
示例
/**
* @Autowired 也可以写在构造器上面
* ·默认优先根据参数类型去匹配
* ·如果匹配到多个类型则会按照参数名字匹配*/
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
/**
* @Autowired 也可以写在方法上面
* ·默认优先根据参数类型去匹配
* ·如果匹配到多个类型则会按照参数名字匹配
* @Qualifier注解也可以作用在属性上,用来被当作id去匹配容器中的对象,如果没有此注解,那么直接按照类型进行匹配
* @param userService*/
@Autowired
public void createUserSerive(@Qualifier("userServiceImpl")UserService userService){
this.userService=userService;
}
@Autowired源码
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* Declares whether the annotated dependency is required.
* <p>Defaults to {@code true}.
*/
boolean required() default true;
}
@Autowired和@Resource都可以自动进行bean注入,但是有一定区别
1.@Autowired:是spring中提供的注解,@Resource:是jdk中定义的注解,依靠的是java的标准
2.@Autowired默认是按照类型进行装配,默认情况下要求依赖的对象必须存在,@Resource默认是按照名字进行匹配的,同时可以指定name属性。
3.@Autowired只适合spring框架,而@Resource扩展性更好
5.对类的注入设置依赖关系@DependsOn
使用@DependsOn标签可以设定当前类的注入需要依赖哪些类,将对应类写入其中后,写入的类会优先于当前类加载到容器中
示例
@Repository//配置对象加载到容器中--标注为数据访问
@DependsOn({"user","role"})
public class UserDaoImpl implements IUserDao
6.将类的注入方式设置为懒加载模式@Lazy
使用@Lazy标签标注类后,该类将不会自动加载,而是在主动调用后才进行加载
示例
@Repository//配置对象加载到容器中--标注为数据访问
@Lazy//配置对象为懒加载
public class UserDaoImpl implements IUserDao
7.设定bean的作用域使用@Scope标签
@Scope标签默认为单例模式,可以根据情况设置为原型模式(多实例)
示例
@Repository//配置对象加载到容器中--标注为数据访问
@Scope(value = "prototype")
public class UserDaoImpl implements IUserDao
8.设定生命周期控制使用@PostConstruct和@PreDestroy两个注释
@PostConstruct设置的是bean初始化时的方法;
@PreDestroy设置的是bean销毁时调用的方法
示例
// 配置对象初始化时调用的方法
@PostConstruct
public void init(){
System.out.println(" userDaoImpl init");
}
// 配置对象销毁时的调用方法
@PreDestroy
public void destroy(){
System.out.println("userDaoImpl destroy");
}
总结
1.bean注册到容器中的方式
2.@Component的细节和使用
3.包扫描配置方式context:component-scan
4.自动注入@Autowired和@Resource
5.对类的注入设置依赖关系@DependsOn
6.将类的注入方式设置为懒加载模式@Lazy
7.设定bean的作用域使用@Scope标签
8.设定生命周期@PostConstruct和@PreDestroy