四.Annotation

    技术2026-04-09  9

    四.Annotation

    Spring注解是从2.5开始

    在主流的SMM开发中,一般是配置文件+注解

    在主流的SpringBoot开发中,一般是纯注解

    1.IOC注解

    普通bean

    @Component该注解可以传递参数,也可以不传递参数当注解存在参数的时候 该参数即为当前bena的id属性值 当注解不存在参数的时候 当前bean的id默认为当前类名,首字母小写

    持久层bean

    @Repository用于与普通bean一致

    业务层bean

    @Service用法与普通bean一致

    控制器bean

    @Controller详情请期待SpringMVC

    注入值

    @Value("值")可以访问properties文件当访问properties文件之后,需要使用配置文件+注解的方式实现

    自动装配

    @Autowired 自动根据byType或者byName查找对应的bean自动识别 @Autowired@Qualifier("ob") 根据bean的id进行装配如果没有找到对应的id值的bean则会报错不建议使用

    spring.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" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- property文件的导入 --> <context:property-placeholder location="classpath:bean.properties"/> <!-- 配置扫描指定包下的注解 base-package:指定包名,指定了包名之后会自动扫描该包下所有的类中的注解 同时如果存在子包,也会扫描所有的子包中的所有的类中的注解 采用递归 扫描bean中的所有类中的注解 --> <context:component-scan base-package="bean"/> </beans>

    注解在bean中的使用

    package bean; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /** * Author:shixiaojun@itany.com * Date:2020/7/2-11:28 */ //当前默认的的当前类名是首字母小写otherBean,当被扫包时自动会注册该bean,id:otherBean @Component("") public class OtherBean { //直接注入值 @Value("1") // 访问properties文件时需要先在spring.xml配置后再使用注解 @Value("${id}") private Integer id; // @Value("admin") @Value("${name}") private String name; @Override public String toString() { return "OtherBean{" + "id=" + id + ", name='" + name + '\'' + '}'; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }

    测试文件test

    public class Test { public static void main(String[] args) throws SomeException { ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); OtherBean otherBean = (OtherBean) ac.getBean("otherBean"); System.out.println(otherBean); } }

    2.AOP注解

    2-1 注解用法

    注解配置AOP和配置文件版本的执行顺序不一致

    优先级最高的是环绕通知

    切入点

    在使用注解的时候,切点表达式也是一个方法通过@Pointcut(切点表达式)进行标注该方法可以没有方法体的内容,是一个空方法定义了切入点之后,当前切入点的id即为当前方法名

    切面

    在类上使用@Aspect进行标注表示当前类是一个切面的类由于切面的类也是由Spring所管理的bean因此,需要使用@Component进行标注

    通知

    前置通知 @Before(value="切入点")value属性指定当前通知所使用的切入点是谁 如果注解的属性中只有value="xxx"这种情况下 此时关键字value=可以省略 如果value属性的值不是一个字符串或者注解属性不止一个value 此时关键字value=不可以省略 正常返回通知 AfterReturning(..)value属性:指定当前通知所使用的切入点是谁returning属性:指定当前接收目标方法返回值的参数 异常通知 @AfterThrowing(..)value属性:指定当前通知所使用的切入点是谁throwing属性:指定当前接收目标方法异常的参数 后置通知 @After(..)value属性:指定当前通知所使用的切入点是谁 环绕通知 @Around(..)value属性:指定当前通知所使用的切入点是谁

    配置spring.xml文件pom依赖记得提前导入

    <?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" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <context:property-placeholder location="classpath:bean.properties"/> <!-- 配置扫描指定包下的注解 base-package:指定包名,指定了包名之后会自动扫描该包下所有的类中的注解 同时如果存在子包,也会扫描所有的子包中的所有的类中的注解 递归 --> <context:component-scan base-package="bean"/> <!-- 扫包,和给业务加事务一样,AOP在数据库操作的提交回滚中有应用 --> <context:component-scan base-package="advice"/> <!-- 使用AOP注解实现配置 --> <!-- 方式一是spring框架自己提供的 --> <!--<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"></bean>--> <!-- 方式一是spring框架自己提供的 --> <aop:aspectj-autoproxy/> </beans>

    1.通知类LogAdvice

    package advice; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; /** * Author:shixiaojun@itany.com * Date:2020/7/2-13:31 */ @Component @Aspect public class LogAdvice { //可以使用通配符 表示使用切入函数的是bean包下的所有类中的所有函数 @Pointcut(value = "execution(* bean.*.*(..))") public void pointcutName(){}; @Around("pointcutName()") public Object around(ProceedingJoinPoint jp) throws Throwable{ Object result = null; try { System.out.println("环绕通知之前置通知"); result = jp.proceed(); System.out.println("环绕通知之正常返回通知"); } catch (Throwable throwable) { System.out.println("环绕通知之异常通知"); } finally { System.out.println("环绕通知之后置通知"); } return result; } // @Before(value = "pointcutName()") 当切入点的值只有value只有一个时可以省略 @Before("pointcutName()") public void before(JoinPoint jp){ System.out.println("前置通知:"+jp.getSignature().getName()+"方法即将执行"); } @AfterReturning(value = "pointcutName()",returning = "returnValue") public void afterReturning(JoinPoint jp,Object returnValue){ System.out.println("正常返回通知:"+jp.getSignature().getName()+"方法执行完成,返回值为:"+returnValue); } @AfterThrowing(value = "pointcutName()",throwing = "e") public void afterThrowing(JoinPoint jp,Exception e){ System.out.println("异常通知:"+jp.getSignature().getName()+"方法执行出错,异常为:"+e); } @After("pointcutName()") public void after(JoinPoint jp){ System.out.println("后置通知:"+jp.getSignature().getName()+"方法执行结束"); } }

    2.测试类

    public class Test { public static void main(String[] args) throws SomeException { ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); SomeService someService = (SomeService) ac.getBean("someServiceImpl"); someService.doSome(); } }

    2-2 配置

    <!-- 使用注解AOP需要进行配置 --> <!-- 有两种方式进行配置 --> <!-- 方式一:使用Spring提供的后处理bean --> <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"></bean> <!-- 方式二:使用AOP命名空间来实现 --> <aop:aspectj-autoproxy/>
    Processed: 0.008, SQL: 9