Spring框架

Spring就是一个能够简化开发和框架整合的技术。

    一、IOC控制反转

      概念:对象创建权由程序转移到外部,这种思想被称为控制反转。

      spring技术对ioc思想进行了实现:spring提供了一个容器,称为ioc容器,用来充当ioc思想中的“外部”。

      ioc容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在ioc容器中统称为bean。

      在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入DI。

    二、spring的入门案例

      1.pom文件中导入坐标     

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.2.10.RELEASE</version>
</dependency>

      2.定义spring管理的类

      

 

 

       3,在配置文件中配置bean路径  

<bean id="BookDao" class="com.itheima.dao.impl.BookDaoImpl"></bean>
<bean id="BookService" class="com.itheima.service.impl.BookServiceImpl"></bean>

      4.在主方法中调用,通过创建容器、加入配置文件、获取bean的方式

//将配置加入到容器中
        ApplicationContext ctx=new ClassPathXmlApplicationContext ("ApplicationContext.xml");
        //获取bean
//       BookDao bookDao = (BookDao) ctx.getBean ("BookDao");
//        bookDao.save ();
        BookService bookService = (BookService) ctx.getBean ("BookService");
        bookService.save ();
    }

    三、DI依赖注入的入门案例

      1.spring管理的类中,删除通过new方式创建的dao对象,创建通过set方法bean入口

   //5.删除业务层中使用new的方式创建的dao对象
    private BookDao bookDao;

    public void save() {
        System.out.println ("book service save ...");
        bookDao.save ();
    }
    //6.set方法,给容器一个入口
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}

     2.在配置文件中配置(要有当前bean的属性名和当前id名)

<bean id="BookService" class="com.itheima.service.impl.BookServiceImpl">
    <!--property是当前bean的属性,name是属性名,ref是当前id名-->
    <property name="bookDao" ref="BookDao"></property>
</bean>

    四、Bean的作用范围

      可以在配置文件中通过scope设置单例和非单例

<bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl" scope="prototype"/>

      为什么bean会默认是单例?

        如果bean不是单例,那么需要一个bean就创建一个,对容器会造成很大的压力,而容器负责管理的的是那些可以复用的bean。

    五、实例化bean的三种方式

      第一种:构造方法

        1.在实现类中创建空参构造方法

      

public class BookDaoImpl implements BookDao {

    public BookDaoImpl() {

        System.out.println("book dao constructor is running ....");
    }
  
public void save() { System.out.println("book dao save ..."); } }

        2.配置文件中配置   

 <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>

      

       第二种:静态工厂实例化bean

        和第一种不同的是,需要创建一个静态工厂类,并且要在这个类中创建对象,返回给实现类

        1.静态工厂与实现类   

//静态工厂创建对象
public class OrderDaoFactory {
    public static OrderDao getOrderDao(){
        System.out.println("factory setup....");
        return new OrderDaoImpl();
    }
}


public class OrderDaoImpl implements OrderDao {

    public void save() {
        
        System.out.println("order dao save ...");
    }
}

        2.配置文件,需要配置工厂方法,工厂路径        

<bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/>

       第三种:使用实例化工厂

          和第二种不同的就是一个是静态,一个普通方法     

//实例工厂创建对象
public class UserDaoFactory {
    public UserDao getUserDao(){
        return new UserDaoImpl();
    }
}

        配置文件(需要创建两个bean,一个是工厂的bean,一个是实现类的bean,实现类的bean需要添加工厂方法和工厂bean)

 <bean id="userFactory" class="com.itheima.factory.UserDaoFactory"/>

    <bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>

        第三种变式:使用FactoryBean

          由于第三种的配置文件编写的可扩展性低,因此可以使用这个变式

          1.在实现类中实现FactoryBean这个方法

//FactoryBean创建对象
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
    //代替原始实例工厂中创建对象的方法
    public UserDao getObject() throws Exception {
        return new UserDaoImpl();
    }

    public Class<?> getObjectType() {
        return UserDao.class;
    }

}

          2.在配置文件中正常编写bean 

<bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/>

    六、bean生命周期

      初始化容器

        1.创建对象(内存分配)

        2.执行构造方法

        3.执行属性注入(Set操作)

        4.执行bean初始化方法

      使用bean

      关闭/销毁容器

    七、setter注入

      引用类型注入

        在业务层中使用set方法进入容器,然后在配置property是当前bean的属性,name是属性名,ref是当前id名    

<bean id="BookService" class="com.itheima.service.impl.BookServiceImpl">
    <!--property是当前bean的属性,name是属性名,ref是当前id名-->
    <property name="bookDao" ref="BookDao"></property>
    <property name="userDao" ref="UserDao"></property>
</bean>

      简单类型注入

        在业务层中进行变量的定义和set方法进入容器,然后在配置文件中通过property标签给指定变量赋值       

<bean id="BookDao" class="com.itheima.dao.impl.BookDaoImpl">
    <property name="number" value="100"></property>
    <property name="season" value="mysql"></property>
</bean>

    八、构造器注入(相当于setter注入换个壳)

      1.引用注入:在业务层实现类中通过实现构造方法,进入容器,然后在配置文件中通过constructor-arg标签指定的bean    

<bean id="UserDao" class="com.itheima.dao.impl.UserDaoImpl"></bean>
<bean id="BookService" class="com.itheima.service.impl.BookServiceImpl">
    <constructor-arg name="bookDao" ref="BookDao"></constructor-arg>
    <constructor-arg name="userDao" ref="UserDao"></constructor-arg>
</bean>

      2.简单注入:通过在业务层实现类中定义变量,然后通过构造器注入进入容器,通过constructor-arg给赋值,但是可以按类型,按名字,按索引进行赋值       

<bean id="BookDao" class="com.itheima.dao.impl.BookDaoImpl">
        <constructor-arg index="0" value="10"></constructor-arg>
        <constructor-arg index="1" value="mysqwl"></constructor-arg>
</bean>

    九、依赖自动装配

      需要用到setter注入,在xml上不用配置其他

<!--依赖自动装配-->
<bean id="BookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
<bean id="UserDao" class="com.itheima.dao.impl.UserDaoImpl"></bean>
<bean id="BookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType"/>

      特征:

        1.自动装配用于引用类型依赖注入,不能对简单类型进行操作

        2、使用byType时,必须保证容器中相同类型的bean是唯一的

        3.使用byName时,必须保证容器中具有指定名称的bean

        4.自动装配优先级低于setter注入与构造器注入 ,同时出现,自动装配配置失效

     十、集合注入     

public class BookDaoImpl implements BookDao {

    private int[] array;

    private List<String> list;

    private Set<String> set;

    private Map<String,String> map;

    private Properties properties;


    public void setArray(int[] array) {
        this.array = array;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    public void save() {
        System.out.println("book dao save ...");

        System.out.println("遍历数组:" + Arrays.toString(array));

        System.out.println("遍历List" + list);

        System.out.println("遍历Set" + set);

        System.out.println("遍历Map" + map);

        System.out.println("遍历Properties" + properties);
    }
}

      配置文件

 <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
        <property name="array">
            <array>
                <value>1</value>
                <value>2</value>
                <value>3</value>
            </array>

        </property>
        <property name="list">
            <list>
                <value>1</value>
                <value>12</value>
                <value>13</value>
            </list>
        </property>
        <property name="map">
            <map>
                <entry key="1" value="221"></entry>
                <entry key="2" value="22"></entry>
                <entry key="3" value="34"></entry>
            </map>
        </property>
        <property name="set">
            <set>
                <value>1</value>
                <value>12</value>
                <value>13</value>
            </set>
        </property>
        <property name="properties">
            <props>
                <prop key="1">2</prop>
                <prop key="12">23</prop>
                <prop key="13">23</prop>
            </props>
        </property>
    </bean>

     容器内容相关总结

      1.BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载

      2.ApplicationContext接口是Spring容器 的核心接口,初始化时bean立即加载

      3.Application接口提供基础的bean操作相关方法,通过其他接口扩展其功能

    十一、注解开发

         1.把xml文件删除,新建一个SpringConfig配置类     

@Configuration //代表xml文件中的那些配置网址那些
@ComponentScan("com.itheima") //代表扫描包语句
public class SpringConfig {
}

        2.生成容器变成AnnotationConfigApplicationContext

public class App1 {
    public static void main(String[] args) {
        ApplicationContext ctx= new AnnotationConfigApplicationContext (SpringConfig.class);
        BookDao bookDao = (BookDao) ctx.getBean ("BookDao");
        System.out.println (bookDao);
        BookService bookService = (BookService) ctx.getBean ("BookService");
        System.out.println (bookService);
    }

    十二、Bean的管理       

        @Scope("singleton")bean的作用范围
         //初始化bean  @PostConstruct
        //销毁bean  @PreDestroy
@Repository
@Scope("singleton") //bean的作用范围,非单例
public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println ("sdsas....");
    }
    //初始化bean
    @PostConstruct
    public void init() {
        System.out.println ("init....");
    }
    //销毁bean
    @PreDestroy
    public void destroy() {
        System.out.println ("destory....");
    }
}
public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext (SpringConfig.class);
       BookDao bookDao = (BookDao) ctx.getBean (BookDao.class);
       BookDao bookDao1 = (BookDao) ctx.getBean (BookDao.class);
        System.out.println (bookDao);
        System.out.println (bookDao1);
        ctx.close (); //使用close之后才会执行销毁操作
    }
}

    十三、spring的自动装配@Autowired

@Service
public class BookServiceImpl implements BooklService {
    @Autowired //自动装配
    @Qualifier("bookDao") //当出现两个一样的实现类时,进行指定的注解,要配合Auto一起使用,而且对应的类中一定添加名称,否则报错
    private BookDao bookDao;

    public void run() {
        System.out.println ("boookService..");
        bookDao.save ();

    }
}

    十四、第三方bean的管理

      在JdbcConfig中配置好要管理的第三方内容    

public class JdbcConfig {
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds=new DruidDataSource ();
        ds.setDriverClassName ("com.mysql.jdbc.Driver");
        ds.setUrl ("jdbc:mysql//localhost:3306/spring_db");
        ds.setUsername ("root");
        ds.setPassword ("123456");
        return ds;
    }
}

      在springconfig中导入配置  

@Configuration
@Import (JdbcConfig.class)
@ComponentScan("com.study")
public class SpringConfig {
}

    2.简单注入

public class JdbcConfig {
    @Value ("${com.mysql.jdbc.Driver}")
    private String DriverClassName;
    @Value ("${jdbc:mysql//localhost:3306/spring_db}")
    private String Url ;
    @Value ("${root}")
    private String Username;
    @Value ("${123456}")
    private String Password;
    @Bean
    public DataSource dataSource(BookDao bookDao){
        System.out.println (bookDao);
        DruidDataSource ds=new DruidDataSource ();
        ds.setDriverClassName (DriverClassName);
        ds.setUrl (Url);
        ds.setUsername (Username);
        ds.setPassword (Password);
        return ds;
    }
}

      3.引用注入

      在springConfig类中添加扫描

      @ComponentScan("com.study")

      在第三方bean中添加参数,让容器自动装配

      @Bean public DataSource dataSource(BookDao bookDao){ System.out.println (bookDao);

    十五、Spring整合MyBatis

      1.导入坐标

       要有spring-context、第三方、mybatis、数据库连接、jdbc、spring整合mybatis的坐标 

<dependencies>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.10.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.16</version>
  </dependency>

  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.6</version>
  </dependency>

  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
  </dependency>

  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.10.RELEASE</version>
  </dependency>

  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.3.0</version>
  </dependency>

        2.使用SqlSessionBeanFactory进行相关资源的整合

           mybaits中jdbc的连接映射资源以及对象属性包的扫描

//使用sqlsessionBeanFactory
@Bean
public SqlSessionFactoryBean sqlSeessionFactoryBean(DataSource dataSource){
    SqlSessionFactoryBean ssfb=new SqlSessionFactoryBean ();
    ssfb.setTypeAliasesPackage ("com.itheima.domain");
    ssfb.setDataSource (dataSource);
    return ssfb;

}

      3.使用MapperScannerConfigurer进行mapper映射基本包的扫描

@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
    MapperScannerConfigurer msc=new MapperScannerConfigurer ();
    msc.setBasePackage ("com.itheima.dao");
    return msc;
}

    十六、Spring整合junit

      1.导入坐标

        要有junit和spring-test的坐标 

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.3.1</version>

</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>5.3.10</version>
</dependency>

      2.创建一个测试类

@RunWith (SpringJUnitRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {
    @Autowired
    private AccountService accountService;

    @Bean
    public void testFindById(){
        System.out.println (accountService.findById (1));
    }
}

    十七、AOP

        面向切面编程,一种编程范式,指导开发者如何组织程序结构

        作用:在不惊动原始设计的基础上为其进行功能的增强

        核心概念:

          连接点:程序执行过程中的任意位置,粒度为执行方法、抛出异常、设置变量等。

           切入点:匹配连接点的式子

          通知:在切入点处执行的操作,也就是共性功能

          通知类:定义通知的类

            切面:描述通知与切入点的对应关系

        入门案例

          1.导入坐标

            新增一个aspectjweaver坐标 

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

          2.制作连接点(dao接口与实现类)

@Repository
public class BookDaoImpl implements BookDao {
    public void run() {
        System.out.println (System.currentTimeMillis ());
        System.out.println ("book dao run....");
    }

    public void update() {
        System.out.println ("book dao update.....");
    }
}

          3.制作共性功能(通知类与通知)

          要在 通知类中添加注解@Aspect告诉容器这是一个通知类,然后创建一个空参构造方法加入注解切入点@Pointcut("execution(void com.study.dao.BookDao.update())") 启动到连接点的方法上,然后在创建一个共性方法,可以切入的方法

@Component
@Aspect
public class MyAdvice {


    @Pointcut("execution(void com.study.dao.BookDao.update())")
    //切入点:启动这个类下的方法
    public void pt(){}

    @Before ("pt()")
    //在这个方法之前执行
    public void method(){
        System.out.println (System.currentTimeMillis ());
    }
}

          4.在spring配置文件中编写注解@EnableAspectJAutoProxy

        Aop工作流程

          1.spring容器启动

          2.读取所有切面配置中的切入点

          3.初始化bean,判定bean对象的类中的方法是否匹配到任意切入点,否,创建对象,是,创建原始对象的代理对象

          4.获取bean的执行方法

        springAOP的本质:代理模式

          核心概念:目标对象、代理

            流程大概就是在执行容器后,系统自动扫描bean,如果有匹配aop的方法,那就有代理,否则就没有

        切入点表达式

          如何正确使用通配符

          

    AOP的五中通知类型

      

  @Pointcut("execution(* com.*.*.*.*())")
    public void pt(){}

    @Pointcut("execution(int com.study.dao.BookDao.select())")
    public void pt2(){}
    //前置通知
//    @Before ("pt()")
    public void method(){
        System.out.println (System.currentTimeMillis ());
    }
    //后置通知
//    @After ("pt()")
    public void method1(){
        System.out.println ("afteradvice");
    }

    //环绕通知
    @Around ("pt2()")
    public Object Around(ProceedingJoinPoint pdj) throws Throwable {
        System.out.println ("before");
        Integer proceed = (Integer) pdj.proceed ();
        System.out.println ("after");
        return proceed+100;
    }

    //4.返回后通知(需要方法正常运行才能通知)


    //5.抛异常后通知

 

    环绕通知@Around注意事项

        1.环绕通知必须依赖形参ProceedingJoinPoint才能实现原始方法的调用,进而实现原始方法调用前后同时添加通知

        2.通知中如果未使用ProceedingJoinPoint对原始方法进行调用将跳过原始方法的执行

        3.对原始方法的调用可以不接受返回值,通知方法设置成void即可,如果接收返回值,必须设定为Object类型

        4.原始方法的返回值如果是void,通知方法的返回值可以设置为void或object

        5.由于无法预知原始方法运行后是否会抛出异常,因此环绕通知方法必须抛出Throwable对象

   十八、Spring事务

        事务的作用:在数据层保障一系列的数据库操作同成功同失败

        SPring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败

        Spring提供了一个接口两个方法和一个实现类用于事务

          

 

       Spring开启事务

        1.业务层中接口方法中添加注解,不要在实现类中添加,便于解耦     

//配置当前接口方法具有事务
@Transactional
public void transfer(String out,String in ,Double money) ;

        2.实现事务方法

//配置事务管理器,mybatis使用的是jdbc事务
 @Bean
public TransactionManager transactionManager(DataSource dataSource){
    DataSourceTransactionManager dm=new DataSourceTransactionManager ();
    dm.setDataSource (dataSource);
    return dm;
 }

        3.在spring配置类中添加事务注解

@EnableTransactionManagement
public class SpringConfig {
}

        Spring事务角色

          事务管理员:发起事务方,在spring中通常指代业务层开启事务的方法(添加@Tranlation)

           事务协调员:加入事务方,在Spring中通常指代数据层方法,也可以是业务层方法

 

         事务传播行为:事务协调员对事务管理员所携带事务的处理态度

          事务传播行为

            REQUIRED默认的,事务管理员就是开启业务的业务层方法,事务协调员就是加入事务方,事务管理员开启了事务,事务协调员加入事务。没开就事务协调员新建

            REQUIRED_NEW,事务管理员开启事务或不开,事务协调员就新建。如转账业务案例,事务生成失败,但是事务管理员的记录日志依旧成功运行。

            SUPPORTS:事务管理员有开他就开,没开就不开

            NOT_SUPPORTS:事务管理员有没有开,他都不开

            NEVER:事务管理员开,他就报错,没开就不开

            NESTED:设置保存点,事务回滚带保存点,就交给客户回滚

 

 

 

 

posted @ 2023-03-12 01:09  LINwenguan  阅读(20)  评论(0编辑  收藏  举报