• 【Java】关于Spring框架的总结 (三)


    前文对 Spring IoC 和 Spring AOP 的实现方法进行了整合。如果有不明白的或有质疑的地方可以评论出来,一起探讨问题,帮助别人也是帮助自己!本文探讨的中心主要放在 Spring 的注解上。对于 Spring ,我也是个初学者,文中也许会出现其他作者总结中出现的内容,在这里感谢原作者。

    注解的基本概念和原理

    注解(Annotation)提供了一种安全的类似注释的机制,为我们在代码中添加信息提供了一种形式化得方法,使我们可以在稍后某个时刻方便的使用这些数据(通过解析注解来使用这些数据),用来将任何的信息或者元数据与程序元素(类、方法、成员变量等)进行关联。其实就是更加直观更加明了的说明,这些说明信息与程序业务逻辑没有关系,并且是供指定的工具或框架使用的。Annotation 像一种修饰符一样,应用于包、类型、构造方法、方法、成员变量、参数及本地变量的申明语句中。

    Annotation 其实是一种接口。通过 Java 的反射机制相关的API来访问 Annotation 信息。相关类(框架或工具中的类)根据这些信息来决定如何使用该程序元素或改变它们的行为。Java 语言解释器在工作时会忽略这些 Annotation ,因此在 JVM 中这些Annotation 是“不起作用”的,只能通过配套的工具才能对这些 Annotation 类型的信息进行访问和处理。

    自定义一个注解

     1 import java.lang.annotation.ElementType;  
     2 import java.lang.annotation.Retention;  
     3 import java.lang.annotation.RetentionPolicy;  
     4 import java.lang.annotation.Target;  
     5   
     6 // 在运行时执行  
     7 @Retention(RetentionPolicy.RUNTIME)  
     8 // 注解适用地方(字段和方法)  
     9 @Target({ ElementType.FIELD, ElementType.METHOD })  
    10 public @interface AnnotationTest {  
    11   
    12     // 注解的name属性  
    13     public String name() default "";  
    14 }  

    有关注解的详细信息可以查阅相关开发文档,这里不再赘述。

    Spring 注解的作用

    Spring 的一个核心功能是 IoC,就是将 Bean 初始化加载到容器中,Bean 是如何加载到容器的,可以使用 Spring 注解方式或者 Spring XML 配置方式。
    Spring 注解方式减少了配置文件内容,更加便于管理,并且使用注解可以大大提高了开发效率!使用 Spring 框架进行开发,注解是必不可少的一部分,可以说是非常重要了。

    使用 Spring 注解需要的 jar 包

    • com.springsource.org.aopalliance-1.0.0.jar
    • com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
    • spring-aop-4.2.5.RELEASE.jar
    • spring-aspects-4.2.5.RELEASE.jar

    注解类介绍

    @Component :标准一个普通的spring Bean类。
    @Repository:标注一个DAO组件类。
    @Service:标注一个业务逻辑组件类。
    @Controller:标注一个控制器组件类。

    使用 @Component 注解定义Bean

    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Repository;
    
    // 通过注解定义一个DAO
    @Component("userDao")
    public class UserDaoImpl implements IUserDao {
    
        @Override
        public void addUser(User user) {
            // 这里并未实现完整数据库操作,仅为说明问题
            System.out.println("add user");
        }
    
    }

    @Component( "userDao" ) 的作用与在 XML 配置文件中编写 <bean id= "userDao"  class= "dao.impl.UserDaoImpl"  /> 等效。

    使用 @Autowired 注解实现Bean组件装配

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.stereotype.Service;
    
    @Service("userService")
    public class UserServiceImpl implements IUserService {
        
        // 声明接口类型的引用和具体实现类解耦合
        @Autowired
        @Qualifier("userDao")
        private IUserDao dao;
        
        @Override
        public void addUser(User user) {
            dao.addUser(user);
        }
    }

    @Autowired 是根据类型进行自动装配的。如果当 Spring 上下文中存在不止一个 UserDao 类型的bean时,就会抛出 BeanCreationException 异常;如果 Spring 上下文中不存在 UserDao 类型的 Bean ,也会抛出 BeanCreationException 异常。我们可以使用@Qualifier 配合 @Autowired 来解决这些问题。

    使用 Java 标准注解 @Resource 完成装配

    import javax.annotation.Resource;
    import org.springframework.stereotype.Service;
    @Service(
    "userService") public class UserServiceImpl implements IUserService { // 查找名为 dao 的 Bean,并注入给 dao 属性 @Resource(name = "userDao") private IUserDao dao;
    @Override
    public void addUser(User user) { dao.addUser(user); } }

    @Resource 有一个 name 属性,默认情况下,Spring 将这个属性的值解释为要注入的 Bean 的名称。

    如果没有显示地指定 Bean 的名称,且无法找到与默认 Bean 名称匹配的 Bean 组件,@Resource 会由按名称查找的方式自动变为按类型匹配的方式进行装配。

    使用注解定义切面

    Spring 通过集成 AspectJ 实现了以注解的方式定义切面,大大减少了配置文件的工作量。AspectJ是一个面向切面的框架,它扩展了 Java 语言,定义了 AOP 语法,能够在编译期提供代码的织入,所以它有一个专门的编译器用来生成遵守字节编码规范的Class 文件。@AspectJ 是 AspectJ 5 新增的功能,使用 JDK 5.0 注解技术和正规的 AspectJ 切点表达式语言描述切面,因此在使用 @AspectJ 之间,需要保证所使用的 JDK 是 5.0 或其以上版本,否则无法使用注解技术

    要进行 AOP 编程,我们首先要在 Spring 配置文件中引入 aop 命名空间

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xmlns:aop="http://www.springframework.org/schema/aop"
     6     xsi:schemaLocation="http://www.springframework.org/schema/beans
     7         http://www.springframework.org/schema/beans/spring-beans.xsd
     8         http://www.springframework.org/schema/context
     9         http://www.springframework.org/schema/context/spring-context-4.2.xsd
    10         http://www.springframework.org/schema/aop 
    11         http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
    12 
    13 </beans>

    使用注解标注切面

    首先看一下增强类代码

     1 import org.apache.log4j.Logger;
     2 import org.aspectj.lang.JoinPoint;
     3 import org.aspectj.lang.ProceedingJoinPoint;
     4 import org.aspectj.lang.annotation.AfterReturning;
     5 import org.aspectj.lang.annotation.AfterThrowing;
     6 import org.aspectj.lang.annotation.Around;
     7 import org.aspectj.lang.annotation.Aspect;
     8 import org.aspectj.lang.annotation.Pointcut;
     9 import org.springframework.stereotype.Component;
    10 
    11 @Aspect
    12 @Component("serviceAdviceLogging")
    13 public class ServiceAdviceLogging {
    14     private Logger logger = Logger.getLogger(ServiceAdviceLogging.class);
    15     
    16     // 注解定义切点 参数为定义切点的表达式部分
    17     @Pointcut("execution(* cn.zdpz.service..*.*(..))")
    18     public void pointcutLogging(){}
    19     
    20     // 注解实现后置增强
    21     @AfterReturning("pointcutLogging()")
    22     public void afterReturning(JoinPoint joinPoint){
    23         String simpleClassName = joinPoint.getSignature().getName();
    24         String methodName = joinPoint.getTarget().getClass().getName();
    25         logger.info(simpleClassName+"-----"+methodName+"后置增强方法");
    26     }
    27     
    28     // 注解实现异常增强
    29     @AfterThrowing(pointcut="pointcutLogging()",throwing="e")
    30     public void afterThrowing(JoinPoint joinPoint,Exception e){
    31         String simpleClassName = joinPoint.getSignature().getName();
    32         String methodName = joinPoint.getTarget().getClass().getName();
    33         logger.info(simpleClassName+"-----"+methodName+"出现异常:"+e.getMessage());
    34     }
    35     
    36     // 注解实现环绕增强
    37     @Around("pointcutLogging()")
    38     public Object around(ProceedingJoinPoint proceedingJoinPoint){
    39      Object obj = null;
    40 try { 41 System.out.println("环绕增强前:"); 42 obj = proceedingJoinPoint.proceed(); 43 System.out.println("环绕增强后:"); 44 } catch (Throwable e) { 45 e.printStackTrace(); 46 }
    47      return obj;
    48 } 49 }

    上面的代码

    使用 @Aspect 注解将 ServiceAdviceLogging 定义为切面

    使用 @AfterReturning 注解将 afterReturning() 方法定义为后置增强

    使用 @AfterThrowing 注解将 afterThrowing() 方法定义为异常增强

    使用 @Around 注解将 around() 方法定义为环绕增强

    一定要看的 注意点总结

    1.被注解的 Java 类当做 Bean 实例,Bean 实例的名称默认是 Bean 类的首字母小写,其他部分不变。@Service 也可以自定义 Bean 名称,但是必须是唯一的!

    2.尽量使用对应组件注解的类替换 @Component 注解,在 spring 未来的版本中,@Controller,@Service,@Repository会携带更多语义。并且便于开发和维护。


    3.指定了某些类可作为 Spring Bean 类使用后,最好还需要让spring搜索指定路径,在Spring配置文件加入如下配置:

    
    
    <!-- 自动扫描指定包及其子包下的所有Bean类 -->
    <context:component-scan base-package="org.springframework.*"/>
    
    

    4.使用 AOP 编程要通过 aop 命名空间的 <aop:aspectj-autoproxy /> 声明自动为 spring 容器中那些配置 @aspectJ 切面的 bean 创建代理,织入切面。 

    <!-- 自动为切面方法中匹配的方法所在的类生成代理对象。 -->
    <aop:aspectj-autoproxy />

    下次更新MyBatis+Spring整合

    
    
  • 相关阅读:
    克隆用户过狗提权
    一个JS引发的血案
    python-标识符(Identifiers)和关键字(keywords)
    提取nmap扫描出来的xml文件
    Hydra扫描姿势
    Senparc.Weixin.MP SDK 微信公众平台开发教程(十二):OAuth2.0说明
    Senparc.Weixin.MP SDK 微信公众平台开发教程(十一):高级接口说明
    Senparc.Weixin.MP SDK 微信公众平台开发教程(十):多客服接口说明
    Senparc.Weixin.MP SDK 微信公众平台开发教程(九):自定义菜单接口说明
    Senparc.Weixin.MP SDK 微信公众平台开发教程(八):通用接口说明
  • 原文地址:https://www.cnblogs.com/xiaotie666/p/LiujinSpring3Summary.html
Copyright © 2020-2023  润新知