1AOP (1)@Component // 声明为一个普通组件,放入spring的容器中,才可以生效 (2)@Aspect // 声明当前类是一个切面
(3)重用切入点表达式:@Pointcut,避免切入点表达式的重复定义,方便维护
(4)前置通知(增强):@Before,在目标方法执行前,自动执行此方法(通过代理实现) @Before("execution(* com.kgc.spring.aspectj.*.*(..))")
(5)后置通知: @After,在目标方法执行后,自动执行,特点:此通知无法获取目标方法的返回值,它的执行跟目标方法是否抛出异常无关(目标方法执行异常,不影响此方法的执行) @After("execution(* com.kgc.spring.aspectj.*.*(..))")
(6) 返回通知: @AfterReturning,在目标方法返回结果后,自动执行,可以获取目标方法的返回值,但是要求@AfterReturning增加属性returning,指定一个参数名,且此参数名必须返回通知方法的一个形参名一致,用于接收目标方法的返回 @AfterReturning(value = "execution(* com.kgc.spring.aspectj.*.*(..))", returning = "result") (7)异常抛出通知: @AfterThrowing,在目标方法抛出异常后,自动执行,可以获取目标方法的抛出异常信息,但是要求@AfterThrowing增加属性throwing,指定一个参数名,且此参数名必须返回通知方法的一个形参名一致,用于接收目标方法的异常 @AfterThrowing(value = "execution(* com.kgc.spring.aspectj.*.*(..))", throwing = "ex") (8)环绕通知:@Around,可以看做是上面四种通知的结合体,一般不建议共用(防止冲突),作用:可以让开发人员在环绕通知的处理方法中,根据不同的业务逻辑,决定是否发起对目标方法的调用 @Around("execution(* com.kgc.spring.aspectj.*.*(..))") (9)通用切入点表达式含义:"execution(* com.kgc.spring.aspectj.*.*(..))"* * 第一个*:代表任意的修饰符,任意的返回值类型 * 第二个*:任意类 * 第三个*:任意的方法 * 第四个..:任意类型和个数的形参 */ (10)@Order(1) // 指定切面优先级,一般都是int型整数,值越小,优先级越高,默认是int最大值(2的31次方-1) (11)<!-- 组件扫描 --> <context:component-scan base-package="com.kgc.spring.aspectj"/> <!-- 基于注解方式实现Aspect切面 --> <!-- 作用:当spring的容器检测到此配置项,会自动将Aspect切面匹配的目标类创建代理对象,放入容器,默认使用的是jdk的动态代理 --> <aop:aspectj-autoproxy/>
2AUTO
(1)
// 以前写法:代码耦合度太高,一旦实现类发生修改,必须修改当前类的代码,更改实现类,无法实现自动识别 // private UserService userService = new UserServiceImpl(); // 组件自动装配,可以实现实体属性类型的自动装配,自动到spring的容器中,根据当前属性的类型或者名称进行注入,如果容器中能匹配到,就直接将实例对象注入到当前实体属性上,无序手动指定 // @Autowired自动装配原理:首先会根据byType方式,进行自动装配,如果能唯一匹配,直接执行自动装配,如果不能唯一匹配(存在同类型多个实例对象),会再次尝试使用byName方式,根据当前实体属性名,到容器中进行匹配(容器中bean的id值),如果能唯一匹配,仍会执行自动装配,如果匹配失败,直接抛出异常 // 默认情况下,@Autowired注解标识的实体属性,必须被装配,如果装配失败,就直接抛出异常,如果不需要校验必须被装配(项目启动,如果装配失败,项目是起不来),通过指定required = false,去除必须执行自动装配的校验(即便容器中找不到装配的实例,也不会抛出异常) // 如果自动装配,容器中存在多个同类型的bean对象,可以使用注解@Qualifier("容器中同类型多个bean的某个id值"),实现指定到容器中,找对应的bean实例对象,进行自动装配 // 底层是如何做的:在指定要扫描的包时,<context:component-scan> 元素会自动注册一个bean的后置处理器:AutowiredAnnotationBeanPostProcessor的实例。该后置处理器可以自动装配标记了@Autowired、@Resource或@Inject注解的属性。 // @Autowired(required = false) // 如果需要允许不必须被装配,可以指定required属性为 false,如果不能自动装配也不会报错,项目正常启动 @Resource // @Autowired是spring提供的,@Resource是jdk提供自动装配注解,装配原理和@Autowired是相反
@Repository // 持久层注解,标识为持久层组件
@Service("myUserService") // 业务层注解,标识为业务层组件,可以起别名
@Autowired // 只要增加此注解,代表实体属性,必须被装配,否则报错,项目启动失败 @Qualifier("userRepositoryMybatisImpl") // @Qualifier注解,如果有多个匹配类型的实例对象,可以指定要装配的bean的id值,实现自动装配,推荐用法 private UserRepository userRepository;// 类型有1个,类型匹配
@Service 强调:组件注解,是用于可以被spring扫描到,创建当前类的实例对象,放到spring的容器中,所以,注解不能加在接口上,都是加在接口的实现类上
<!-- 基于spring的注解方式实现自动装配 --> <!-- 组件扫描:注解标识的组件,必须通过组件扫描配置,才可以添加到spring的容器中 --> <!-- spring创建容器对象时,如果解析到component-scan组件扫描配置,会将base-package指定的基包(父包)及其子包中所有增加了分层注解的类,自动创建实例对象,放入容器中,交给spring容器管理,省去了手动配置bean的繁琐操作 1、默认情况下:spring自动将分层注解(@Controller,@Service, @Repository,@Component)标识的类(不是接口),自动创建实例对象放入容器中,使用的bean的标识id值为:对应类名首字母小写 就相当于帮我们手动添加了配置:<bean id="分层注解标识类的类名首字母小写" class="分层注解标识类的全类名">...</bean> 2、如果不使用默认的类名首字母小写,可以使用注解的value属性,指定一个自定义的id值,如:@Service(value = "自定义的id值"),注解只有value属性,可以省略value指定,简化为:@Service("自定义的id值") 3、实际上,Spring框架没有能力识别一个组件到底是不是它所标记的类型,即便使用@Component注解,添加到@Controller组件的控制层类上,也可以自动创建实例对象放入容器 4、分组组件注解的目的:就仅仅是为了方便开发人员明确当前注解标注的类所对应的角色,在使用上,没有什么区别的,建议使用时,按照官方定义的组件类型进行使用,不要乱用,防止组件模糊不清 --> <context:component-scan base-package="com.kgc.spring.annotation"> <!-- 1、指定扫描(包含扫描):只会扫描指定的类或者某类组件(使用分层注解),加入到容器中,但是必须要配合父标签的use-default-filters使用,默认值是true,就是全部扫描,指定扫描是无效的,如果要生效必须将其改为false --> <!-- 指定扫描某类组件,type="annotation",expression="某类组件注解的全类名" --> <!--<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>--> <!-- 指定扫描某个类,type="assignable",expression="某个类的全类名" 了解,很少使用--> <!--<context:include-filter type="assignable" expression="com.kgc.spring.annotation.controller.UserController"/>--> <!-- 2、排除扫描(剔除扫描):直接排除指定的类或者某类组件(使用分层注解),不加入到容器中,除了排除外的其它组件,仍然会被添加到容器中,不需要配合父标签的use-default-filters使用,默认就是全部扫描,排除就是在全部扫描基础上,剔除的 --> <!-- 排除扫描某类组件,type="annotation",expression="某类组件注解的全类名" --> <!--<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>--> </context:component-scan>
<!-- spring中bean的自动装配方式: 1、byType:根据类型自动装配 根据实例属性的类型,到容器中,根据类型进行唯一匹配,如果可以匹配到对应类型的bean的实例,就会执行自动装配,如果不能唯一匹配(同类型的bean有多个),会报错,并装配失败 如果容器中匹配不到对应类型的bean,不会报错,不执行自动装配,实体属性对应为null 2、byName:根据名称自动装配 根据实体属性的属性名,到容器中,跟bean的id属性值,进行唯一匹配,如果能成功匹配,执行自动装配,如果匹配不到,不执行自动装配,实体属性为null,不会存在匹配多个情况(bean的id值是唯一) -->