Spring注解开发

Spring注解开发

Spring的开发大体可分为两类:XML配置和注解开发。
本文主要讲解纯注解开发的形式。实际应用中可根据情况结合进行。

一、配置文件

配置文件分为两种方式:XML配置文件、Config配置类

1、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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <!--自动扫描指定的包,这个包下的注解就会生效-->
    <context:component-scan base-package="com.zyh.pojo"/>
</beans>

2、Config配置类

自己创建一个Config类,在创建的类上面加上@Configuration注解,该类就变为Spring的配置类。

@Configuration
@ComponentScan({"com.zyh.pojo","com.zyh.service"})//扫描包下的bean对象
//@Import(MyConfig2.class) 导入其他配置类
public class SpringConfig {
    @Bean
    public People people(){
        return new People();
    }
}

这些代码就创建了一个基础的配置文件。实际上是取代了xml当中的以下代码:
其中上图配置类中的@ComponentScan("com.zyh.pojo")等同于xml方法中中配置文件中的<context:component-scan base-package="com.zyh.pojo"/>
@Configuration等同于其余代码。
如上代码所示,一个简单的配置类就创建好了,也就相当于创建好了一个容器,那么怎么将外面的bean对象注入到容器中呢?下面介绍两种方式。

二、创建并注入bean对象

将bean对象注入Config配置类的方法有两种:

1.在配置类中创建方法,上面@Bean。

@Configuration
@ComponentScan({"com.zyh.pojo","com.zyh.service"})
//@Import(MyConfig2.class) 导入其他配置类
public class SpringConfig {
    @Bean
    public People people(){
        return new People();
    }
}

2.在实体类上加@Component

在实体类上加@Component ,config配置文件扫描到该注解会自动创建bean对象。

@Component("user")  // 不加括号名,则名字默认未类名(首字母小写)
// 相当于配置文件中 <bean id="user" class="当前注解的类"/>
public class User {
    @Value("猪猪")
    // 相当于配置文件中 <property name="name" value="猪猪"/>
    public String name;
    //要给出getter方法,但可以不用给出setter方法了
    public String getName() {
        return name;
    }
}

Spring提供了@Component注解的三个衍生注解:

  • @Controller:用于表现层bean定义
  • @Service:用于业务层bean定义
  • @Repository:用于数据层(dao层)bean定义

这四中注解是等价的关系,都能被@ComponentScan扫描到。
问:那为什么有了@Compent,还需要@Bean呢?
如果你想要将第三方库中的组件装配到你的应用中,在这种情况下,是没有办法在它的类上添加@Component注解的,因此就不能使用自动化装配的方案了,但是我们可以使用@Bean,当然也可以使用XML配置。

3. 更改初始化容器代码

从这可以和xml对比这看,配置类初始化时改成了new AnnotationConfigApplicationContext(SpringConfig.class);
但此处只写了初始化容器代码,至于简单测试的话下面还需要写ctx.getBean()来拿到具体的对象进行操作。

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
    public static void main(String[] args) {
        // 加載xml配置文件初始化容器
        //ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 加載配置類初始化容器
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        User user = ctx.getBean("user",User.class);
        System.out.println(user.getName());
    }
}

以上说的是从配置方法上分的两大类。下面说的是纯注解方式的一些要点。

三、依赖注入(自动装配)

创建完bean对象后,那类中的简单属性怎么赋值,复杂类属性怎么转配呢?
解答:
类中的简单属性用@Value("名称")进行赋值。
类中的复杂类属性,用下面两种注解进行装配:
@Autowired:自动按类型装配
@Qualifier("people") :注入指定的bean对象,当有多个相同的类型时,就要用这种方式。
案例:User类中添加了People类作为属性。

@Component("user")
// 相当于配置文件中 <bean id="user" class="当前注解的类"/>
public class User {
    @Autowired   // 自动按类型装配
    @Qualifier("people")  // 注入指定的bean对象
    private People people;
    @Value("猪猪")
    // 相当于配置文件中 <property name="name" value="猪猪"/>
    private String name;
    //要给出getter方法,但可以不用给出setter方法了
    public String getName() {
        return name;
    }
    public void save(){
        people.say();
    }
}

测试类中,可以用user.save()方法,调用的people中的say()方法,就可以知道People类装配成功。

四、加载properties配置文件

加载配置文件,最熟悉最基础的就是jdbc.properties配置文件,无非就是两个问题:
1.config配置注解的形式怎么加载到这个文件?
2.加载好之后怎么用?
properties文件以jdbc为例,切只写了name作为示范:
在这里插入图片描述

  1. @PropertySource("jdbc.properties")让config配置文件加载到properties
@Configuration
@ComponentScan({"com.zyh.pojo","com.zyh.service"})
@PropertySource("jdbc.properties")  
//@Import(MyConfig2.class) 导入其他配置类
public class SpringConfig {

}
  1. 在需要赋的属性上用@Value("${name}"),这样该属性就和properties中的name的key对应上。测试中调用getName会打印出root。
@Component("user")
// 相当于配置文件中 <bean id="user" class="当前注解的类"/>
public class User {
    @Value("${name}")
    private String name;
    //要给出getter方法,但可以不用给出setter方法了
    public String getName() {
        return name;
    }
}

注意事项:

  1. 加载多个properties文件格式:@PropertySource({"jdbc.properties","jdbc2.properties"})
  2. 不支持使用通配符,例如:@PropertySource("*.properties") 会报错。

五、Spring整合MyBatis

mybatis的作用是简化jdbc的开发,简单的讲就是mybatis框架要整合jdbc进来,spirng框架要把mybatis整合进来,一层套一层。

1.原生jdbc配置

原生jdbc的properties文件如下所示:

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/zyhtest?userSSL=false&&serverTimezone=GMT&&allowPublicKeyRetrieval=true
jdbc.username=root
jdbc.password=1234

2.mybatis加入jdbc

将jdbc文件加入到mybatis.xml文件中,并把以上代码存在在DataSource区域内,作为一个资源对象。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="jdbc.properties"></properties> <!--读入jdbc文件-->
    <typeAliases>
        <package name="com.zyh.pojo"/>
    </typeAliases>
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <package name="com.zyh.dao"></package> <!--扫描mapper层的接口-->
    </mappers>
</configuration>

3.增加配置类

到现在为止,mybatis的所有配置都在外部文件中写完了,但还没有整合进spring框架当中。要想整合进去,需要将这些配置导入配置类中。为了清晰分类,最好创建一个专属于jdbc的配置类和专属于mybatis的配置类。
(1)jdbc配置类
将jdbc中的内容加载到datasource对象当中。

public class JdbcConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String userName;
    @Value("${jdbc.password}")
    private String password;
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}

(2)mybatis配置类
mybatis中最主要的就是创建sqlsessionfactory,在spring中提供了一个专门的类:SqlSessionFactoryBean,要报datasource对象装配进去。

public class MybatisConfig {
    //对应mybatis.xml文件中其他内容
    // 如果通过@Bean方式创建的对象,要想在其中再注入对象的话,在方法中加参数即可,参数会按类型自动到容器中匹配注入。
    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
        SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
        ssfb.setTypeAliasesPackage("com.zyh.pojo");
        ssfb.setDataSource(dataSource);
        return ssfb;
    }
    // 对应mybatis.xml配置文件中的<mapper>标签中的内容
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
        MapperScannerConfigurer mscf = new MapperScannerConfigurer();
        mscf.setBasePackage("com.zyh.dao");
        return mscf;
    }
}

创建完SqlSessionFactoryBean对象,等同于mybatis.xml配置中<mapper>以外的部分,下面单独创建mapper对象即等同于原来这个xml文件。
(3)导入主配置类
利用@Import({JdbcConfig.class,MybatisConfig.class})导入上述两个配置类。

@Configuration
@ComponentScan("com.zyh")
@PropertySource("jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class}) // 导入其他配置类
public class SpringConfig {
}

整体思维图如下:
在这里插入图片描述

六、注解实现AOP

我们总线上的编程是纵向编程思想,需要用到的主要实际类方法就那些,但在公司中基于业务的考虑,会要求加入在功能的前后加入通知、日志、异常抛出通知等一系列的附加功能,这些功能就需要在service层横切进去,在代理中加入。
而这些操作,在spring的aop中已经帮你做好了接口,你只需要实现它即可。例如要在方法之前插入就实现 MethodBeforeAdvice接口。
AOP所遇到的问题有一下几点:

  • 在什么位置切入?
  • 怎么切入?
  • 怎么实现附加功能?

1.在什么位置切入

先定义切入点,切入点包含具体切入到哪个包下的哪个类。注解的方式如下:
@Pointcut("execution(int com.zyh.service.UserService.select())")
ececution(方法类型 扫描包.方法名(参数个数))

//相当于保留针头,现将切入点创建出来,后面任何方法只要怼入即可
//    @Pointcut("execution(void com.zyh.service.UserService.add())")
//    @Pointcut("execution(* com.zyh.service.UserService.add(*))") //方法里必须有参数(失败)
//    @Pointcut("execution(* com.*.*.*.add())")   // (成功)一个 *. 对应一层包,可以使这一层的任意一个包,但只能匹配这一层
//    @Pointcut("execution(* *..*(..))")   // (成功)代表任意返回值,任意包下的任意方法的任意参数。即所有方法全部匹配。
                                       // *.. 代表包下的任意内容,可以跨越好几层
    @Pointcut("execution(* com.zyh.*.*Service.*e(..))")   // (成功)代表:zyh包下的任意包下的以Service结尾的接口(或类)下的以e结尾的方法。
    private void pt(){}
    @Pointcut("execution(int com.zyh.service.UserService.select())")
    private void pt2(){}

2.怎么切入

AOP有五种通知类型:
@Befor:前置通知
@After:后置通知
@Around:环绕通知
@AfterReturning:返回后通知
@AfterThrowing:抛出异常后通知
已知上面定义好了切入点,将切入点传入这五种注解中,就将切点和连接点对应起来。如下所示代表在select方法执行前,先执行输出before语句。

@Before("pt()")
    public void before(){
        System.out.println("before");
    }

3.怎么实现附加功能

至于怎么实现附加功能,在上述注解下面的方法中写即可。
注:
至此spring注解开发的基础内容基本就是这些,但这只是最基础部分,只是为了更好地梳理逻辑,更好地理解其作用。剩下的仍需要慢慢研究。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猪大侠0.0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值