Spring

目录

一.为什么要学spring?

二、Spring的特点

三、IOC(控制反转)

四、DI(依赖注入)方式(常用)

五、Spring配置

六、自动装配

七、注解开发

八、脱离XML配置Spring

九、AOP

代理模式:

AOP详解:面向切面编程

十、整合Mybatis

十一、Spring声明式事务


一.为什么要学spring?

        1.简化开发

               Spring是一个十分优秀的框架,它的目的是为了简化企业级Java的开发。使用过Servlet开发网站的都清楚,Servlet包含了大量重复性的代码,我们需要花大量的时间去重复写,而Spring可以避免这种重复的操作;

        2.大势所趋

                市面上几乎所有公司都在用这门技术,为了以后的就业需求,我们必须掌握

        3.后续学习

                在之后学习的SpringMVC、SpringBoot、SpringCould等流行技术,都是以Spring为基础的,没有Spring作为基础,无法掌握高层次的技术。

二、Spring的特点

        在学习一门技术之前,除了了解他的用途之外,也需要了解它的一些优缺点,以便在以后的开发中扬长避短。

        Spring的用途就是用来解决企业级应用开发的复杂性
优点:
    1、开源、免费的框架(容器)
    2、轻量级、非入侵式的框架
    3、控制反转(IOC)、面向切面编程(AOP)
    4、支持事物处理、对框架整合

总结:Spring就是一个轻量级的控制反转(IOC)、面向切面编程(AOP)的框架。

三、IOC(控制反转)

控制反转是一种设计思想,主要作用是用来减少类和类之间的耦合度

IOC容器持有了创造、查找依赖对象的控制权,由容器来进行注入组合对象,从而达到松散耦合的目的;

DI(依赖注入)是实现IOC的一种方式

        依赖:类依赖于容器

        注入:IOC注入某个对象,注入了所需的外部资源(对象、资源、常量)

本质上来说,IOC和DI是不同维度的同一种表现,也以理解为:IOC为Bean的注册,DI为Bean的初始化

四、DI(依赖注入)方式(常用)

  1. 构造器注入
    <bean id="person01" class="com.xawl.wsf.Person" >
        <!--下标注入-->
        <constructor-arg index="0" value="李四"></constructor-arg>
        <constructor-arg index="1" value="18"></constructor-arg>
    </bean>
    
    <bean id="people02" class="com.chai.lesson2.Person">
        <!--类型注入-->
        <constructor-arg type="String" value="王五"></constructor-arg>
        <constructor-arg type="int" value="19"></constructor-arg>
    </bean>
    
    <bean id="people03" class="com.chai.lesson2.Person">
        <!--参数名注入-->
        <constructor-arg name="name" value="王五"></constructor-arg>
        <constructor-arg name="age" value="19"></constructor-arg>
    </bean>
    
  2. Set注入
    <bean id="hello" class="com.xawl.wsf.HelloSpring">
        <!--    
            name的值与set方法setName对应,若无,无法运行
        -->
        <property name="name" value="张三"></property>
    </bean>
  3. 其他注入
     
    <!-- p标签注入:--> <!-- c标签注入:-->
    
    <!-- 配置文件-->
    <?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:p="http://www.springframework.org/schema/p"
    xmlns:c="http://www.springframework.org/schema/c"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    
    
    <bean id="people_p" class="com.xawl.day02.pojo.People" p:age="12" p:name="李四"/>
    
    <bean id="people_c" class="com.xawl.day02.pojo.People" c:age="21" c:name="张三"/>

五、Spring配置

  1. 别名配置 alias
    <!--    别名alias  -->
    
    <alias name="people" alias="p1"/>
    
    
    <!--  name别名设置,支持多别名 --->
    
    <bean id="people" class="com.xawl.day02.pojo.People" name="p1,p2,p3"/>
  2. xml文件整合
    <!--    多个xml 文件合并为一个-->
    <beans>
        <import resource="ioc.xml"/>
        <import resource="bean.xml"/>
    </beans>
  3. 作用域
    <beans>
        <!--    原型模式,每次getbean取出的为不同对象-->
        <bean id="people01" class="com.xawl.day02.pojo.People" scope="prototype">
    
        <!--    单例模式,每次getbean取出的为同一对象-->
        <bean id="people02" class="com.xawl.day02.pojo.People" scope="singleton">
    </beans>
    //原型模式构建bean测试
    public class Testt {
        public static void main(String[] args) {
            ApplicationContext ioc = new ClassPathXmlApplicationContext("day02.xml");
            People p1 = ioc.getBean("people01", People.class);
    
            People p2 = ioc.getBean("people01", People.class);
            System.out.println("原型测试:"+(p1==p2));
        }
    }
    //输出结果:原型测试:false
    
    
    
    
    //单例模式构建bean测试
    public class Testt {
        public static void main(String[] args) {
            ApplicationContext ioc = new ClassPathXmlApplicationContext("day02.xml");
            People p1 = ioc.getBean("people02", People.class);
    
            People p2 = ioc.getBean("people02", People.class);
            System.out.println("单例测试:"+(p1==p2));
        }
    }
    //输出结果:单例测试:true

六、自动装配

首先说一下什么是装配:依赖注入的本质就是装配,装配是依赖注入的具体行为

装配的方式:

        1.XML显示装配

        2.Java显示装配

        3.隐式装配

        两种显示装配的方式,在之前已经了解,自动装配基于的就是隐式装配,根据给定的条件,查找符合条件(名称、类型)的数据,进行装配。

                1.根据名称自动装配

                 条件:自动注入bean的id名称必须和Set方法的名称关联,且唯一,否则装配失败

   实体类:

public class User {
    private String name;
    private int age;
    private String sex;
    private Dog dog;//自动装配目标
    private Cat cat;//自动装配目标
}

   配置文件:

<!--根据名称自动装配-->   
<bean id="user" class="com.xawl.auto.pojo.User" autowire="byName"/>

<!--自动装配目标-->   
<bean id="dog" class="com.xawl.auto.pojo.Dog" >
    <property name="sing" value="汪汪"></property>
    <property name="dogName" value="狗狗"></property>
</bean>

<!--自动装配目标-->   
<bean id="cat" class="com.xawl.auto.pojo.Cat" >
    <property name="sing" value="喵喵喵"></property>
    <property name="carName" value="喵"></property>
</bean>

        2.根据类型自动装配

        条件:此类型全局唯一,否则装配失败

<!--根据名称自动装配-->   
<bean id="user" class="com.xawl.auto.pojo.User" autowire="byType"/>

七、注解开发

        开发前提:

        ①导入约束

<?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
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
</beans>

        ②开启注解支持

    <!--    开启注解支持-->
  <context:annotation-config/>

        ③对于定义注册bean类注解,需要进行包扫描

<context:component-scan base-package="com.xawl.annotation.pojo"/>

        注解分类:
        ①注册bean

                @Component:组件,放于类上 (等价于:<bean id="类首字母小写" class="本类">)

        ②衍生的注册bean

                MVC三层架构
                Dao层 -----------------@Repository
                service层 -------------@Service
                controller层 -----------@Controller
                其他层------------------@Component
           这四个注解功能一样,用于注册,分层不同

        ③属性注入注解
      
         @Value("XXX")放于set方法、变量上  (等价于<property name="本属性" vlaue="XXX">)

        ④作用域注解

                @Scope("singleton")/prototype  放于类上 单例作用域/原型作用域

        ⑤自动装配注解

                @Autowired 

                        自动装配,先通过类型查找,再通过名字,都没找到注入失败;找到多个运行失败

                @Qualifier(value="××")

                        指定名称式自动装配,value=目标装配的id,需要保证类型一致

                @Resource    @Resource(name = "××")

                        功能和以上两个注解结合起来一样,先通过类型查找,再通过名称,名称可指定

        总结:

                xml:更万能,适用于任何场合,维护方便
                注解:不是自己的类使用不了,维护复杂

                使用:xml:管理Bean    注解:属性的注入

八、脱离XML配置Spring

       也就是用通过注解使java类替代xml文件的功能

        1.注册类:@Configuration  也会被注册,代表这是配置类
        2.扫描包:@componentScan("")扫描包
        3. @Import:多合一,引入其他的配置类 等价于<import>
        4.@bean  相当于bean标签
        5.方法名,返回值  方法名:id属性   返回值:class属性
        通过AnnotationConfig来获取

        

//注册类标志,表示此类为配置类
@Configuration
//引入别的配置类
@Import(SpringConfig01.class)
//扫描包
@ComponentScan("com.xawl.annotation.pojo")
public class SpringConfig {
    //bean标签
    @Bean
    //id="people01" class="....People"
    public People people01(){
        return new People();
    }
}

测试类:

    @Test
    public void test01(){
        ApplicationContext ioc = new AnnotationConfigApplicationContext(SpringConfig.class);
        People bean = (People)ioc.getBean("people01");
        System.out.println(bean);
    }

九、AOP

AOP底层层理:动态代理模式(基于反射)

代理模式:

        1.静态代理模式:

                ①.角色分析:
                    抽象角色:接口、抽象类实现
                    真实角色:被代理的角色(房东)
                    代理角色:代理真实角色(代理)+附属操作
                    客户:访问代理的人(租房的人)
                ②.优点:
                    使角色操作更纯粹,不需要设计公共的业务
                    公共业务交给代理角色,单一职责原则
                    公共业务发生扩展时,方便管理
                ③.缺点
                    一个角色产生一个代理,代码量翻倍

        2.动态代理模式

                与静态代理区别:使用反射机制动态生成代理类

                Proxy 用于生产动态代理的实例
                InvocationHandler 用于调用处理程序并返回结果
                结合了静态代理的所有优点
                动态代理代理接口,一般针对一类业务
                一个动态代理可以代理多个类,只要实现了同一接口

AOP详解:面向切面编程

        需求:在程序运行期间,需要增加日志等功能,若在程序中直接修改,是不符合开闭原则的。在不修改原有代码的情况下,并结合代理模式,AOP诞生了

        面向切面:在程序运行时,动态的将代码切入到指定的类中指定的方法、指定的位置的编程,就是面向切面编程

        实现:

       1.导包

        maven下导入

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>

        2.引入约束

<?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: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/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>

        3.三种实现方式

                ①API接口实现

定义通知类,继承API接口               

API接口:
前置通知:MethodBeforeAdvice
后置通知:AfterAdvice
返回通知:AfterReturningAdvice
异常通知:ThrowsAdvice
//前置通知
public class AfterLog implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("方法调用前,调用了"+method.getName()+"方法");
    }
}
//返回通知
public class BeforeLog implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("返回通知:返回值:"+returnValue+"method:"+method.getName());
    }
}

配置XML文件

<!--注册Bean-->
    <bean id="sql" class="com.xawl.wsf.aop.SqlImpl"/>
    <bean id="before" class="com.xawl.wsf.aop.BeforeLog"/>
    <bean id="after" class="com.xawl.wsf.aop.AfterLog"/>
<!--    定义切入点-->
    <aop:config>
        <!--定义切入点表达式-->
        <aop:pointcut id="notice" expression="execution(* com.xawl.wsf.aop.SqlImpl.*(..))"/>
        <!--执行环绕增强-->
        <aop:advisor advice-ref="before" pointcut-ref="notice"/>
        <aop:advisor advice-ref="after" pointcut-ref="notice"/>
    </aop:config>

测试:

@Test
public void test() {
    ApplicationContext ioc = new ClassPathXmlApplicationContext("ioc.xml");
    Sql sql = (Sql) ioc.getBean("sql");
    sql.insert();
}

                ②切面类实现

定义切面类

//切面类
public class Notice {
    public void befor(){
        System.out.println("方法运行前");
    }
    public void after(){
        System.out.println("方法运行后");
    }
    public void returning(){
        System.out.println("返回通知");
    }
}

配置xml

<!-- 注册实体类 -->
<bean id="sql" class="com.xawl.wsf.aop.SqlImpl"/>
<bean id="ice" class="com.xawl.wsf.aop.Notice"/>
<aop:config>
    <!--引入切面类-->
    <aop:aspect ref="ice">
        <!--定义切入点表达式-->
        <aop:pointcut id="notice" expression="execution( * com.xawl.wsf.aop.SqlImpl.*(..))"/>
        <!--增强环绕通知,绑定切面类的方法-->
        <aop:before method="befor" pointcut-ref="notice"/>
        <aop:after method="after" pointcut-ref="notice"/>
        <aop:after-returning method="returning" pointcut-ref="notice"/>
    </aop:aspect>
</aop:config>

                ③注解实现

配置文件

<!--开启注解支持-->
<aop:aspectj-autoproxy/>
<!--注册bean-->
<bean id="sql" class="com.xawl.wsf.aop.SqlImpl"/>
<bean class="com.xawl.wsf.aop.NotIceZj"/>

注解实体类

//注解方式实现
//标记为切切面类
@Aspect
public class NotIceZj {
    //前置通知
    @Before("execution(* com.xawl.wsf.aop.SqlImpl.*(..))")
    public void befor(){
        System.out.println("+注解++运行前");
    }
    //后置通知
    @After("execution(* com.xawl.wsf.aop.SqlImpl.*(..))")
    public void after(){
        System.out.println("注解方法运行后");
    }
    //返回通知
    @AfterReturning("execution(* com.xawl.wsf.aop.SqlImpl.*(..))")
    public void returning(){
        System.out.println("返回通知");
    }
    //环绕通知
    @Around("execution(* com.xawl.wsf.aop.SqlImpl.*(..))")
    public void around(ProceedingJoinPoint pr) throws Throwable {
        System.out.println("环绕前");
        //执行方法
        Object proceed = pr.proceed();
        System.out.println("环绕后");
    }
}

十、整合Mybatis

Mybatis与spring整合,使用spring容器管理对象

步骤:       

1.导包

        需要的包:junt、mybatis、mysql、spring、aop、mybatis-spring

        <!--数据库包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!--Mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--spring支持-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
        <!--用于spring操作数据库-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
        <!--mybatis-spring-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>
        <!--aop-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>

2.编写XML配置文件

(1)mybatis-config.xml 主要用于配置别名、set设置(可被spring全完取代)

<?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>
<!--  set设置  -->
    <settings>
        <setting name="" value=""/>
    </settings>
<!--  别名  -->
    <typeAliases>
        <package name="com.xawl.affair.pojo"/>
    </typeAliases>
</configuration>

(2)spring-mybatis.xml

       主要作用是配置数据源、获取SqlSessionFactory对象、获取SqlSession对象

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--1.DataSource 获取数据源,配置连接数据库的信息-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;userUnicode=true&amp;characterEncoding=utf-8"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>

    <!--2.获取SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--传入dataSource值-->
        <property name="dataSource" ref="dataSource"/>
        <!--绑定Mybatis配置文件,两个相辅相成-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!--mapper绑定xml,绑定所有,一劳永逸-->
        <property name="mapperLocations" value="classpath:com/xawl/affair/dao/*.xml"/>
    </bean>

    <!--3. 获取SqlSessionTemplate 与SQLSession相同-->
    <bean name="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>
</beans>

(3)applicationContext.xml

        用于融合其他XML,并用来配置注册bean

<?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
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
<!--导入其他xml-->
    <import resource="spring-mybatis.xml"/>
<!--扫描包-->
    <context:component-scan base-package="com.xawl.affair.dao"/>
<!--   注解开启后,可省略 -->
<!--    <bean id="userMapper" class="com.xawl.affair.dao.UserMapperImpl" >-->
<!--        <property name="sqlSession" ref="sqlSession"/>-->
<!--    </bean>-->
</beans>

3.XML语句、增删改查

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--绑定一个mapper接口-->
<mapper namespace="com.xawl.affair.dao.UserMapper">
    
</mapper>

4.Mapper接口文件(dao层,与Mybatis一致)

5.书写Mapper实现类

        (1)set方法注入SqlsessionTemplate

//set方法注入
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
   this.sqlSession = sqlSession;
}

        (2)继承SqlSessionDaoSupport类,此类中封装了SqlsessionTemplate的构造器、set方法,可直接使用其getSession()方法获得SqlsessionTemplate对象

public class CourseMapperImpl extends SqlSessionDaoSupport implements CourseMapper{
    //继承SqlSessionDaoSupport类,此类内置了构造、set方法,可直接使用set方法获得
    public List<Course> getcourse() {
        //getSqlSession()方法获取对象
        CourseMapper mapper = getSqlSession().getMapper(CourseMapper.class);
        return mapper.getcourse();
    }
}

                此时,XML只需给其父类注入SqlSessionFactory对象即可

<!--使用继承SqlSessionDaoSupport方法,给其父类直接注入sqlSessionFactory即可-->
<bean id="courseMapper" class="com.xawl.spring.dao.CourseMapperImpl">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

6.测试,通过spring容器获取结果

@Test
public void test01(){
    ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserMapper userMapper = ioc.getBean("userMapper", UserMapper.class);
    List<User> list = userMapper.getall();
    for (User user : list) {
        System.out.println(user);
    }
}

十一、Spring声明式事务

事务:
        要么都成功,要么都失败,要求:完整性,一致性
        ACID原则:
                原子性:一个事务是一个整体,不可分割,对其操作要么都做,要么都不做
                一致性:数据库事务是从一个一致性状态变成另一个一致性状态
                隔离性:并发时,防止数据损坏
                持久性 :事务提交后,结果不可被影响

声明式事务:

        结合AOP,在符合OCP原则的基础上,加入事务

        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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">
</beans>

        2.XML配置

        原理:AOP

        可以指定任意包、任意类、任意方法加入事务

<!--  1.添加对象  -->
<bean id="manager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <constructor-arg ref="dataSource"/>
</bean>
<!--  2.导入引用文件——tx 配置事务通知  -->
<tx:advice id="interceptor" transaction-manager="manager">
    <tx:attributes>
        <!--     给哪些方法配置事务-->
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>
<!--    配置事务切入-->
<aop:config>
    <aop:pointcut id="peiont" expression="execution(* com.xawl.affair.dao.*.*(..))"/>
    <aop:advisor advice-ref="interceptor" pointcut-ref="peiont"/>
</aop:config>

        3.测试

        必须是在同一方法中开启事务,触发异常时进行回滚

@Override
public int setage(Map<Object, Object> map) {
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    return mapper.setage(map);
}
public int setageall(Map<Object, Object> map1,Map<Object, Object> map2){
    int set1 = setage(map1);
    int set2 = setage(map2);
    if(set1+set2<2){
        throw new RuntimeException("失败");
    }
    return set1+set2;
}

总结:spring主要核心思想IOC、AOP,一个降低耦合性,一个面向切面开发,熟练掌握其思想,并熟悉注解的使用,为下一步打下基础。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值