我是靠谱客的博主 可爱雪糕,最近开发中收集的这篇文章主要介绍Spring注解式开发四、Spring注解式开发,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

四、Spring注解式开发

1. 概述

Spring是开发中必不可少的一个框架,基于传统的xml方式配置太过繁琐,从spring2.5之后注解的出现可以大大简化配置。

1.1 Xml优缺点

优点:

  • 把类与类之间松解偶,修改方便,容易扩展
  • 容易和其他系统进行数据交互
  • 对象之间的关系一目了然

缺点:

  • 配置冗长,需要额外维护,影响开发效率
  • 类型不安全,校验不出来,出错不好排查

1.2 注解优缺点

优点:

  • 简化配置
  • 使用起来直观且容易,提升开发的效率
  • 类型安全,容易检测出问题

缺点:

  • 修改起来比xml麻烦
  • 如果不项目不了解,可能给开发和维护带来麻烦

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

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

2. 开启注解

2.1 组件扫描

  • 组件扫描(component scanning):Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件,使Spring中的注解生效
  • 对于扫描到的组件,Spring有默认的命名规则:使用首字母小写的类名,作为默认bean的名称,也可以在注解中通过value属性值标识组件的名称
  • 在Spring的配置文件中声明<context:component-scan>标签,实现组件扫描
  • <context:component-scan>标签的base-package属性指定一个需要扫描的基础类包,Spring容器将会扫描这个基础类包里及其子包中的所有类
  • 当需要扫描多个包时,可以使用逗号分隔;或配置多个<context:component-scan>标签
<!-- 组件扫描-->
<context:component-scan base-package="com.newcapec.bean"/>
<context:component-scan base-package="com.newcapec.dao"/>
<context:component-scan base-package="com.newcapec.service"/>
<context:component-scan base-package="com.newcapec.controller"/>

2.2 扫描过滤

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

<!-- 粗粒度过滤 -->
<context:component-scan base-package="com.newcapec" resource-pattern="bean/*.class"/>

细粒度的过滤,可采用子标签<context:include-filter>表示要包含的目标类和<context:exclude-filter>表示要排除在外的目标类。其中type属性有以下5种:

  1. annotation:过滤器扫描使用注解所标注的那些类,通过expression属性指定要扫描的注释
  2. assignable:过滤器扫描派生于expression属性所指定类型的那些类
  3. aspectj:过滤器扫描与expression属性所指定的AspectJ表达式所匹配的那些类
  4. regex:过滤器扫描类的名称与expression属性所指定正则表示式所匹配的那些类
  5. custom:使用自定义的org.springframework.core.type.TypeFliter实现类,该类由expression属性指定

**注意:**若使用<context:include-filter>去过滤扫描内容,要在use-default-filters="false"的情况下,不然会失效,被默认的过滤机制所覆盖。在use-default-filters="false"的情况下,exclude-filter是针对include-filter里的内容进行排除

不包含:

@Component
public class Dog {
    @Override
    public String toString() {
        return "Dog";
    }
}

@Component
public class SmallDog extends Dog {
    @Override
    public String toString() {
        return "SmallDog";
    }
}
<!-- 细粒度过滤 -->
<!-- 默认扫描规则:base-package下所有的类,所有的子包,所有子包下的类都会被扫描 -->
<context:component-scan base-package="com.newcapec">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    <context:exclude-filter type="assignable" expression="com.newcapec.bean.Dog"/>
</context:component-scan>

仅包含:

<context:component-scan base-package="com.newcapec" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

3. 配置Bean

  • @Component:基本注解,标识一个受Spring管理的组件
  • @Respository:标识持久层组件
  • @Service:标识服务层(业务层)组件
  • @Controller:标识表现层组件

公有属性value:表示Bean的名称

@Component
public class Person {
    private int id;
    private String name;
    private double money;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + ''' +
                ", money=" + money +
                '}';
    }
}
public interface DemoDao {
    void insertDemo();
}
@Repository("demoDao")
public class DemoDaoImpl implements DemoDao {
    @Override
    public void insertDemo() {
        System.out.println("dao中实现数据新增........");
    }
}
public interface DemoService {
    void insertDemo();
}
@Service("demoService")
public class DemoServiceImpl implements DemoService {
    @Override
    public void insertDemo() {
        System.out.println("service中实现数据新增........");
    }
}
@Controller
public class DemoController {
    public void insertDemo(){
        System.out.println("controller中实现数据新增.......");
    }
}

测试

public class AnnotationTest {

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

        Person p1 = ac.getBean("person", Person.class);
        System.out.println(p1);

        DemoDao demoDao = ac.getBean("demoDao", DemoDao.class);
        demoDao.insertDemo();

        DemoService demoService = ac.getBean("demoService", DemoService.class);
        demoService.insertDemo();

        DemoController demoController = ac.getBean("demoController", DemoController.class);
        demoController.insertDemo();

        SmallDog smallDog = ac.getBean("smallDog" ,SmallDog.class);
        System.out.println(smallDog);

        Dog dog = ac.getBean("dog", Dog.class);
        System.out.println(dog);
    }
}

4. 组件装配

@Value:为组件属性注入字面值

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

@Autowired:默认按照类型装配

  • 构造方法,普通属性(即使是非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的名称作为键值
@Service("demoService")
public class DemoServiceImpl implements DemoService {

    @Autowired(required = false)
    @Qualifier("demoDao")
    private DemoDao demoDao;
    @Override
    public void insertDemo() {
        System.out.println("service中实现数据新增........");
        demoDao.insertDemo();
    }
}

@Resource:默认按照名称装配

  • @Resource注解要求提供一个bean名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为bean的名称
  • @Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动装配策略,而使用type属性时则使用byType自动装配策略。如果既不指定name也不指定type属性,这时将先使用byName自动装配策略,装配不成功,再才用byType装配
@Controller
public class DemoController {
    @Resource
    private DemoService demoService;
    public void insertDemo(){
        System.out.println("controller中实现数据新增.......");
        demoService.insertDemo();
    }
}

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 实例。

//该注解表示这个类为javaConfig类
@Configuration
public class MyConfig {
    //该注解表示:将一个叫做dept的对象放入IOC容器中
    @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);
    }
}

6. AOP的实现

6.1 开启AOP注解

<!-- 开启AOP注解 -->
<aop:aspectj-autoproxy/>

6.2 AOP中使用的注解

  • @Aspect:配置切面类
  • @Before:配置前置通知
  • @After:配置后置通知
  • @AfterReturning:配置返回通知
  • @AfterThrowing:配置异常通知
  • @Order:配置切面优先级
  • @Pointcut:配置切点表达式
@Component
@Aspect
@Order(2)
public class LogAspect {

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

    //公共切点表达式
    @Pointcut("execution(* com.newcapec.dao.DemoDaoImpl.*(..))")
    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.dao.DemoDaoImpl.*(..))")
    public void beforeM(){
        System.out.println("OtherAspect的beforeM方法.....");
    }
}

7. 事务管理

7.1 启用事务注解

<!-- 1.配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!-- 注入数据源-->
    <property name="dataSource" ref="dataSource"/>
</bean>
<!-- 2.开启事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

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 {
}

最后

以上就是可爱雪糕为你收集整理的Spring注解式开发四、Spring注解式开发的全部内容,希望文章能够帮你解决Spring注解式开发四、Spring注解式开发所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部