Spring总结

目录

Spring是什么?

 Spring IOC/DI

DI的实现方式:

设值注入:

 构造注入:

自动装配:

 基于注释的自动装配:

什么是Aop?

 术语解释:

Spring Aop通知分类:

实现原理:

 基于xml实现aop:

基于注解实现aop:

JdbcTemplate:

整合Mybatis:


Spring是什么?

Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架

 Spring IOC/DI

IOC(Inversion Of Control)控制反转,是面向对象编程中的一种设计原则。

控制:控制对象的创建,整个生命周期的管理,依赖关系管理。

反转:原来是程序创建,现在是第三方容器创建。

优点:1、降低了耦合度

            2、灵活性提高

 UserDao userDao = new UserDaoImpl();

UserDao userDao = Spring客户端.getBean(id标识);

Spring客户端指的是通过ApplicationContext接口实现的类,例如:ClassPathXmlApplicationContext、AnnotationConfigApplicationContext

具体代码:

        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext".xml)

        UserDao userDao = context.getBean("userDao",UserDao.class);

 其中,最常见的方式是DI(Dependency Injection)依赖注入。它是一种实现IOC的编程思想。

DI的实现方式:

构造函数注入:将依赖对象作为参数传递给类的构造函数。

设值(setter)注入:通过类的setter方法将依赖对象注入到类中。

自动装配:自动分析对象的依赖关系,并自动将需要的依赖注入到对象中。

        包括:按名称自动装配、按类型自动装配、按构造函数自动装配和基于 Qualifier 的自动装配等。其中以按名称和按类型自动装配为最常用的两种。

此外,还有字段注入、方法注入等。

byName按名称自动装配:按照 Spring Bean 的名称进行匹配,如果当前 Bean 的名称和其他 Bean 的名称一致,则自动注入。可以使用 @Resource注解实现默认按名称自动装配,也可以使用@Autowired @Qualifier(id标识)

byType按类型自动装配:根据 Bean 类型进行匹配,如果当前 Bean 的类型和其他 Bean 的类型一致,则自动注入。可以使用 @Autowired 注解实现默认按类型自动装配。

设值注入:

public class EmpServiceImpl implements EmpService {

    private EmpDao empDao;
    private String name;

    public String getName() {
        return name;
    }

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

    public EmpDao getEmpDao() {
        return empDao;
    }

    public void setEmpDao(EmpDao empDao) {
        this.empDao = empDao;
    }

    @Override
    public void show() {
        System.out.println("注入的name:"+this.name);
        empDao.show();
    }
}
<bean id="empDao"  class="com.m0_54698212.dao.EmpDaoImpl"></bean>
    <bean id="empService" class="com.m0_54698212.service.EmpServiceImpl">
        <!--        注入引用的对象EmpDao  ref:引用 指定id对应的bean-->
        <property name="name" value="员工姓名"/>
        <property name="empDao" ref="empDao"/>
    </bean>

 构造注入:

注意:默认获取bean的时候,调用的是无参构造实例化,确保有无参构造。

public class EmpServiceImpl implements EmpService {

    private EmpDao empDao;
    private String name;

    public EmpServiceImpl(EmpDao empDao, String name) {
        this.empDao = empDao;
        this.name = name;
    }

    public EmpServiceImpl() {
    }

    @Override
    public void show() {
        System.out.println("注入的name:"+this.name);
        empDao.show();
    }
}
<bean id="empDao"  class="com.m0_54698212.dao.EmpDaoImpl"></bean>
   <!--    构造注入-->
    <bean id="empService" class="com.m0_54698212.service.EmpServiceImpl">
<!--        <constructor-arg index="0" ref="empDao"/>-->
<!--        <constructor-arg index="1" value="员工姓名"/>-->
        <constructor-arg name="name" value="员工姓名"/>
        <constructor-arg name="empDao" ref="empDao"/>
    </bean>

自动装配:

public class EmpServiceImpl implements EmpService {

    private EmpDao empDao;
    private String name;

    public EmpDao getEmpDao() {
        return empDao;
    }

    public void setEmpDao(EmpDao empDao) {
        this.empDao = empDao;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public void show() {
        System.out.println("注入的name:"+this.name);
        empDao.show();
    }
}
<!--    autowire="byName" :需要提供get set 方法; 根据名字 :属性名  bean的名字进行匹配 -->
<!--    autowire="byType":根据类型自动注入: 属性的类型 匹配 bean的类型 -->
<bean id="empService" class="com.m0_54698212.service.EmpServiceImpl" ></bean>

 基于注释的自动装配:

步骤:

        1、开启组件扫描

        2、使用注解定义 Bean

        3、基于注解方式实现依赖注入

注解说明
@Component该注解用于描述 Spring 中的 Bean,它是一个泛化的概念,仅仅表示容器中的一个组件(Bean),并且可以作用在应用的任何层次,例如 Service 层、Dao 层等。 使用时只需将该注解标注在相应类上即可。
@Repository该注解用于将数据访问层(Dao 层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Service该注解通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Controller该注解通常作用在控制层(如 Struts2 的 Action、SpringMVC 的 Controller),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
<!--    注解扫描-->
    <context:component-scan base-package="com.m0_54698212"/>
</beans>
@Repository
public class AccountDaoImpl implements AccountDao{
    private List<Account> accounts=new ArrayList<>();
    @Override
    public List<Account> list() {
        System.out.println("查询账户");
        return accounts;
    }
}
@Service
public class AccountServiceImpl implements AccountService{
    @Autowired
    private AccountDao accountDao;
    @Override
    public List<Account> list() {
        return accountDao.list();
    }
}

什么是Aop?

AOP,即面向切面编程(Aspect-Oriented Programming),是对OOP(面向对象)思想的补充 。主要是为了解决程序中的横切关注点(Cross-Cutting Concerns)问题而提出的一种技术。

横切关注点包括日志记录、事务处理、安全控制等与业务逻辑无关的功能模块。

切点(Pointcut):定义了那些类的哪些方法需要被切入。

通知(Advice):定义了切入到方法之前、方法之后、方法返回后或方法抛出异常时所要执行的代码。

切面(Aspect):将切点和通知结合起来,定义了一组关于哪些类的哪些方法在何时被切入的规则。

 术语解释:

  • Joinpoint(连接点):指那些被拦截到的点,在Spring中,指可以被动态代理拦截目标类的方法。

  • Pointcut(切入点):指要对哪些Joinpoint进行拦截,即被拦截的连接点。

  • Advice(通知):指拦截到Joinpoint之后要做的事情,即对切入点增强的内容。

  • Target(目标):指代理的目标对象。

  • Weaving(植入):指把增强代码应用到目标上,生成代理对象的过程。

  • Proxy(代理):指生成的代理对象。

  • Aspect(切面):切入点和通知的结合

Spring Aop通知分类:

  • before(前置通知):通知方法在目标方法调用之前执行

  • after(后置通知):通知方法在自标方法返回或异常后调用

  • after-returning (返回后通知):通知方法会在目标方法返回后调用

  • after-throwing(抛出异常通知):通知方法会在目标方法抛出异常后调用

  • around(环绕通知):通知方法会将目标方法封装起来

实现原理:

动态代理:

1、目标接口:jdk动态代理

2、目标类:cglib动态代理

 基于xml实现aop:

步骤:    

        1、引入依赖包:spring-aop,spring-aspects

        2、定义切面类

        3、在切面类中定义通知方法

        4、在xml中配置

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.3.25</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>5.3.25</version>
    </dependency>
public class Trans {

    /**
     *
     * @param joinPoint 连接点
     */
    public void startTran(JoinPoint joinPoint){
        System.out.println("目标方法的签名:"+joinPoint.getSignature());
        System.out.println("开启事务");
    }


    /**
     * 提交事务
     * @param joinPoint
     * @param result 目标方法返回的结果
     */
    public void commitTran(JoinPoint joinPoint,Object result){
        System.out.println("目标方法的签名:"+joinPoint.getSignature());
        String methodName = joinPoint.getSignature().getName();
        System.out.println("提交事务"+methodName);
        }


    }
}
<!--    将切面类配置成bean-->
    <bean id="trans" class="com.m0_54698212.aspect.Trans"/>
    <aop:config>
        <aop:aspect ref="trans">
            <!--        切入点-->
            <aop:pointcut id="p1" expression="execution(* com.m0_54698212.service.*.*(..))"/>
<!--            配置前置通知-->
            <aop:before method="startTran" pointcut-ref="p1"/>
<!--            正常返回通知-->
            <aop:after-returning method="commitTran" returning="result" pointcut-ref="p1"/>
        </aop:aspect>
    </aop:config>

基于注解实现aop:

通知类型的注解分为5种:

注解通知
@Before通知方法会在目标方法调用之前执行
@After通知方法会在目标方法返回或异常后调用
@AfterReturning通知方法会在目标方法返回后调用
@AfterThrowing通知方法会在目标方法抛出异常后调用
@Around通知方法会在目标方法封装起来
@Configuration//容器类,相当于applicationContext.xml文件
@ComponentScan(basePackages = "com.m0_54698212")
@EnableAspectJAutoProxy//启用aop的自动代理
public class App 
{
    @Bean//将方法的返回值,配置成一个bean
    public UserService userService1(){
        return new UserServiceImpl();
    }
}
@Component
@Aspect
public class MyTrans {
    @Pointcut("execution(public * com.m0_54698212.service.*.*(..))")
    public void pt(){}
    @Pointcut("execution(public * com.m0_54698212.dao.*.*(..))")
    public void pt2(){}
    //JoinPoint:连接点对象:目标对象中的连接点:获取到要增强的目标方法的信息
    //通知
    @Before("pt()")
    public void startTrans(JoinPoint joinpoint){
        System.out.println("目标对象"+joinpoint.getTarget());
        System.out.println("方法签名"+joinpoint.getSignature());
        //目标方法
        String methodName = joinpoint.getSignature().getName();
        System.out.println("在目标方法"+ methodName + "开始事务");
    }
//    @After("pt()")
    public void commitTrans(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("在目标方法"+ methodName + "提交事务");
    }
//    @AfterReturning(value = "pt()",returning = "res")
    public void afterReturning(JoinPoint joinPoint,Object res){
        System.out.println("目标方法正常返回果后的通知:");
        System.out.println("目标方法返回的结果:"+res);
    }
//    @AfterThrowing(value = "pt()",throwing = "e")
    public void afterThrowing(JoinPoint joinPoint,Exception e){
        System.out.println("目标方法发生异常后才会有通知:");
        System.out.println(e);
    }
//    @Around("pt()")
    public Object around(ProceedingJoinPoint joinPoint){
        Object res = 0;
        try {
            System.out.println("环绕通知开始:");
            //目标方法的执行
            res = joinPoint.proceed();
            System.out.println("目标方法结果:"+res);
        } catch (Throwable e) {
            System.out.println("环绕通知异常:"+e);
        } finally {
            System.out.println("环绕通知结束");
        }
        return res;
    }
}
<context:component-scan base-package="com.m0_54698212"/>
   <!--    启用aop自动代理-->
   <aop:aspectj-autoproxy />
public class TestAnnotation {
    @Test
    public void test1(){
        ApplicationContext context = new AnnotationConfigApplicationContext(App.class);
        UserService userService = context.getBean("userServiceImpl",UserService.class);
        userService.add(new User("发发发",16,"男"));
    }
}

运行结果:

JdbcTemplate:

JdbcTemplate 是 Spring 框架提供的一种简化 JDBC 开发的工具类。

JdbcTemplate 对 JDBC 进行了封装,使得开发者可以更加方便、快捷地操作数据库。在实际开发中,JdbcTemplate 可以帮助我们避免一些低层次的 JDBC 编程错误,提高了开发效率和代码的可维护性。

特点: 

1. 封装了 JDBC,提供了更加简洁、方便的操作方式。

2. 提供了查询、更新、批量更新等多种操作方法,可以处理复杂的 SQL 语句。

3. 提供了异常处理、结果集自动映射和资源自动释放等功能,使得开发更加稳定、高效。

<!--引入 jdbc.properties 中的配置-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>

    <!--定义数据源 Bean-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <!--数据库连接地址-->
        <property name="url" value="${jdbc.url}"/>
        <!--数据库的用户名-->
        <property name="username" value="${jdbc.username}"/>
        <!--数据库的密码-->
        <property name="password" value="${jdbc.password}"/>
        <!--数据库驱动-->
        <property name="driverClassName" value="${jdbc.driver}"/>
    </bean>

    <!--定义JdbcTemplate Bean-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--将数据源的 Bean 注入到 JdbcTemplate 中-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

整合Mybatis:

步骤:

        1、引入依赖包

        2、配置数据源

<dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.3</version>
    </dependency>
    <!--    mybatis-spring桥梁-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.3</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.31</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.3.24</version>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.20</version>
    </dependency>
<!--    启用注解扫描 -->
    <context:component-scan base-package="com.m0_54698212"></context:component-scan>
<!--    加载db.properties-->
    <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!--    配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
            init-method="init"
            destroy-method="close">
        <property name="url" value="${url}"></property>
        <property name="username" value="${user}"></property>
        <property name="password" value="${pwd}"></property>
        <property name="driverClassName" value="${driver}"></property>
<!--        初始化连接数量-->
        <property name="initialSize" value="${initialSize}"></property>
        <!--        最大活动连接数-->
        <property name="maxActive" value="${maxActive}"></property>
        <!--        最小空闲连接数,连接池保留不低于空闲连接的数量-->
        <property name="minIdle" value="${minIdle}"></property>
        <!--        获取连接时最大的等待时间,超过未获取到连接就抛出异常-->
        <property name="maxWait" value="${maxWait}"></property>
        <!--        验证连接是否成功的命令-->
        <property name="validationQuery" value="select 1;"></property>
    </bean>

<!--    配置SqlSessionFactoryBean-->
    <bean id="sessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--        引用数据源-->
        <property name="dataSource" ref="dataSource"></property>
<!--        配置别名包-->
        <property name="typeAliasesPackage" value="com.m0_54698212.entity"></property>
<!--        指定xml文件-->
        <property name="mapperLocations" value="classpath:mapper/*.xml"></property>
    </bean>

<!--    配置dao接口的扫描-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sessionFactoryBean"></property>
<!--        指定dao接口所在的包-->
        <property name="basePackage" value="com.m0_54698212.dao"></property>
    </bean>
/**
 * @Author {那蓝桉}
 * @Date: 2023/05/26/ 15:26
 * @description
 */
@Configuration//容器类,将类配置成类似于xml的容器
@ComponentScan(basePackages = "com.m0_54698212")//开启注解扫描
@PropertySource(value = "db.properties")//加载键值对properties文件
@MapperScan("com.m0_54698212.dao")//配置dao接口的扫描
public class AppConfig {
    //@Value用来获取属性文件中的属性值
    @Value("${user}")
    private String user;
    @Value("${url}")
    private String url;
    @Value("${pwd}")
    private String password;
    @Value("${driver}")
    private String driver;
    @Value("${initialSize}")
    private Integer initialSize;
    @Value("${maxActive}")
    private Integer maxActive;
    @Value("${minIdle}")
    private Integer minIdle;
    @Value("${maxWait}")
    private Integer maxWait;

    @Bean
    public DataSource dataSource(){
//        配置数据源
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setUsername(user);
        dataSource.setPassword(password);
        dataSource.setDriverClassName(driver);
        dataSource.setInitialSize(initialSize);
        dataSource.setMaxActive(maxActive);
        dataSource.setMinIdle(minIdle);
        dataSource.setMaxWait(maxWait);
        return dataSource;
    }

    //配置SqlSessionFactoryBean
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean() throws IOException {
        SqlSessionFactoryBean factoryBean=new SqlSessionFactoryBean();
        //引用数据源
        factoryBean.setDataSource(dataSource());
        //配置别名包
        factoryBean.setTypeAliasesPackage("com.m0_54698212.entity");
        //配置类,开启小驼峰命名
        org.apache.ibatis.session.Configuration configuration=new org.apache.ibatis.session.Configuration();
        configuration.setMapUnderscoreToCamelCase(true);
        factoryBean.setConfiguration(configuration);
        //路径资源匹配解析器对象
        PathMatchingResourcePatternResolver resolver=new PathMatchingResourcePatternResolver();
        //指定xml文件
        factoryBean.setMapperLocations(resolver.getResources("mapper/*.xml"));
        return factoryBean;
    }
}
public class Test{
    @Test
    public void test(){
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        MaterialService materialService = context.getBean(MaterialService.class);
        List<Material> list = materialService.findAll();
        System.out.println(list);
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值