栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【Spring从入门到实战教程】第四章 Spring 注解式开发详解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Spring从入门到实战教程】第四章 Spring 注解式开发详解

四、Spring 注解式开发

    JavaWeb项目经历的阶段:
        1、Servlet + JSP / Servlet + 模板引擎,该阶段XML配置很少,但是需要从基础代码开始编写;
        2、SSH(Spring/Struts2/Hibernate) / SSM(Spring/SpringMVC/Mybatis),该阶段无需从基础代码开始编写,但是需要大量的XML配置;
        3、SSM,该阶段无需从基础代码开始编写,采用注解+XML配置;
        4、SpringBoot,零配置(XML),采用注解+yml配置;

4.1 概述

    从 Java 5 开始,Java 增加了对注解(Annotation)的支持,它是代码中的一种特殊标记,可以在编译、类加载和运行时被读取,执行相应的处理。开发人员可以通过注解在不改变原有代码和逻辑的情况下,在源代码中嵌入补充信息。

    Spring是开发中必不可少的一个框架,基于传统的xml方式配置太过繁琐,Spring 从 2.5 版本开始提供了对注解技术的全面支持,我们可以使用注解来实现自动装配,简化 Spring 的 XML 配置。

4.1.1 Xml优缺点

优点:

  • 降低类与类之间的耦合,修改方便,容易扩展;

  • 容易和其他系统进行数据交互;

  • 对象之间的关系一目了然;

缺点:

  • 配置冗长,需要额外维护,影响开发效率;

  • 类型不安全,校验不出来,出错不好排查;

4.1.2 注解优缺点

优点:

  • 简化配置;

  • 使用起来直观且容易,提升开发的效率;

  • 类型安全,容易检测出问题;

缺点:

  • 修改起来比xml麻烦;

  • 如果不项目不了解,可能给开发和维护带来麻烦;

注解简单概括:写起来比较简单、方便,看起来也简洁,但是修改麻烦;

Xml配置概括:写起来比较灵活、修改方便,但是写和维护麻烦;

4.2 开启注解 4.2.1 组件扫描

    Spring 默认不使用注解装配 Bean,因此我们需要在 Spring 的 XML 配置中,通过 元素开启 Spring Beans的自动扫描功能。开启此功能后,Spring 会自动从扫描指定的包(base-package 属性设置)及其子包下的所有类,如果类上使用了 @Component 注解,就将该类装配到容器中。

  • 组件扫描(component scanning):Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件,使Spring中的注解生效;

  • 对于扫描到的组件,Spring有默认的命名规则:使用首字母小写的类名,作为默认bean的名称,也可以在注解中通过value属性值标识组件的名称;

  • 在Spring的配置文件中声明标签,实现组件扫描;

  • 标签的base-package属性指定一个需要扫描的基础类包,Spring容器将会扫描这个基础类包里及其子包中的所有类;

  • 当需要扫描多个包时,可以使用逗号分隔;或配置多个标签;








注意:在使用 元素开启自动扫描功能前,首先需要在 XML 配置的一级标签 中添加 context 相关的约束。

4.2.2 扫描过滤
  • 4.2.2.1 粗粒度过滤

如果仅希望扫描特定的类而非基包下的所有类,可使用resource-pattern属性过滤特定的类:


 

@Autowired和@Resource:自动装配注解,即自动注入。

@Autowired:可以应用到 Bean 的属性变量、setter 方法、非 setter 方法及构造函数等,默认按照 Bean 的类型进行装配。

  • 构造方法,普通属性(即使是非public),一切具有参数的方法都可以使用@Authwired注解;

  • 所有使用@Autowired注解的属性都要求依赖的bean对象必须存在。当Spring找不到匹配的bean装配属性时,会抛出异常。若该属性允许为null值,可以设置@Authwired注解的required属性为false;

  • 当IOC容器里存在多个类型兼容的bean对象时,通过类型的自动装配将无法工作。此时可以在@Qualifier注解里提供bean的名称,Spring会通过名称自动装配;

  • @Authwired注解也可以应用在数组类型的属性上,此时Spring将会把所有匹配的bean进行自动装配;

  • @Authwired注解也可以应用在集合属性上,此时Spring读取该集合的类型信息,然后自动装配所有与之兼容的bean;

  • @Authwired注解用在java.util.Map上时,若该Map的键值为String,那么Spring将自动装配与之Map值类型兼容的bean,此时bean的名称作为键值;

  • 旧版本的IDEA,如果接口没有实现类,使用@Authwired注解会报红,但是不影响使用。新版本IDEA不影响。

@Qualifier:与 @Autowired 注解配合使用,会将默认的按 Bean 类型装配修改为按 Bean 的实例名称装配,Bean 的实例名称由 @Qualifier 注解的参数指定。

@Service("personService")
public class PersonServiceImpl implements PersonService {

    
    //private PersonDao personDao = new PersonDaoImpl();

    
    

    
    //@Autowired
    @Autowired(required = false)
    @Qualifier("personDaoImpl")
    private PersonDao personDao;

    @Override
    public void insertPerson() {
        System.out.println("PersonServiceImpl insertPerson()执行了...");

        if (personDao != null) {
            personDao.insertPerson();
        }
    }
}
@Test
public void testAutowired(){
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

    try {
        PersonService personService = ac.getBean("personService", PersonService.class);
        personService.insertPerson();
    }catch (Exception e){
        System.out.println(e.getMessage());
    }
}

@Resource:作用与 Autowired 相同,区别在于 @Autowired 默认按照 Bean 类型装配,而 @Resource 默认按照 Bean 的名称进行装配。@Resource 中有两个重要属性:name 和 type。

  • @Resource注解要求提供一个bean名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为bean的名称;

  • Spring 将 name 属性解析为 Bean 的实例名称,type 属性解析为 Bean 的实例类型。

  • 如果指定 name 属性,则按实例名称进行装配;

  • 如果指定 type 属性,则按 Bean 类型进行装配;

  • 如果都不指定,则先按 Bean 实例名称装配,如果不能匹配,则再按照 Bean 类型进行装配;如果都无法匹配,则抛出 NoSuchBeanDefinitionException 异常。

@Controller
public class PersonController {

    @Resource
    private PersonService personService;

    public void insertPerson(){
        System.out.println("PersonController insertPerson()执行了...");

        personService.insertPerson();
    }
}
4.5 Java Config

    JavaConfig,是在 Spring 3.0 开始从一个独立的项目并入到 Spring 中的。JavaConfig 可以看成一个用于完成 Bean 装配的 Spring 配置文件,即 Spring 容器,只不过该容器不是 XML文件,而是由程序员使用 Java 自己编写的 Java 类。

Dept.java:

public class Dept {
    private int deptno;
    private String dname;

    public int getDeptno() {
        return deptno;
    }

    public void setDeptno(int deptno) {
        this.deptno = deptno;
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "deptno=" + deptno +
                ", dname='" + dname + ''' +
                '}';
    }
}

Emp.java:

public class Emp {
    private int empno;
    private String ename;
    private Dept dept;

    public int getEmpno() {
        return empno;
    }

    public void setEmpno(int empno) {
        this.empno = empno;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "empno=" + empno +
                ", ename='" + ename + ''' +
                ", dept=" + dept +
                '}';
    }
}

配置类:

    定义 JavaConfig 类,在类上使用@Configuration 注解,将会使当前类作为一个 Spring 的容器来使用,用于完成 Bean 的创建。在该 JavaConfig 的方法上使用@Bean,将会使一个普通方法所返回的结果变为指定名称的 Bean 实例。

@Configuration
public class MyConfig {
    
    @Bean("dept")
    public Dept getDept() {
        Dept dept = new Dept();
        dept.setDeptno(10);
        dept.setDname("研发部");
        return dept;
    }

    //该注解表示:将一个叫做emp的对象放入IOC容器中
    //并且通过byType的方式注入dept
    @Bean(name = "emp", autowire = Autowire.BY_TYPE)
    public Emp getEmp() {
        Emp emp = new Emp();
        emp.setEmpno(8001);
        emp.setEname("张三");
        return emp;
    }
}

测试:

public class JavaConfigTest {

    @Test
    public void test(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        Dept dept = ac.getBean("dept", Dept.class);
        System.out.println(dept);

        Emp emp = ac.getBean("emp", Emp.class);
        System.out.println(emp);
    }
}
4.6 AOP的实现 4.6.1 开启AOP注解

4.6.2 AOP中使用的注解
  • @Aspect:配置切面类

  • @Before:配置前置通知

  • @After:配置后置通知

  • @AfterReturning:配置返回通知

  • @AfterThrowing:配置异常通知

  • @Order:配置切面优先级

  • @Pointcut:配置切点表达式

@Component
@Aspect
@Order(2)
public class LogAspect {

    @Before("execution(* com.newcapec.service.impl.*.*(..))")
    public void beforeMethod() {
        System.out.println("AOP日志记录:前置通知......");
    }

    //公共切点表达式
    @Pointcut("execution(* com.newcapec.service.impl.*.*(..))")
    public void exp() {
    }

    @After("exp()")
    public void afterMethod() {
        System.out.println("AOP日志记录:后置通知......");
    }

    @AfterReturning(value = "exp()", returning = "result")
    public void afterReturnMethod(Object result) {
        System.out.println("AOP日志记录:返回通知......" + result);
    }

    @AfterThrowing(value = "exp()", throwing = "ex")
    public void afterThrowMethod(Exception ex) {
        System.out.println("AOP日志记录:异常通知......" + ex);
    }
}
@Component
@Aspect
@Order(1)
public class OtherAspect {

    @Before("execution(* com.newcapec.service.impl.*.*(..))")
    public void beforeM(){
        System.out.println("OtherAspect的beforeM方法.....");
    }
}
4.7 事务管理 4.7.1 启用事务注解


    
    



4.7.2 事务注解

在事务方法上加注解@Transactional:

@Transactional(propagation = Propagation.REQUIRES_NEW,isolation = Isolation.READ_COMMITTED,
                readOnly = true,timeout = 20,rollbackFor = {ClassNotFoundException.class})
public void transfer(int fromId, int toId, double money) throws Exception {
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/887767.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号