• spring相关


    spring 控制反转

    控制权的转移,由spring负责对象的创建和维护。

    注入方式

    自动装配:@Autowired

    此处暂略

    setter方法注入

    需要创建bean的成员对象的setter方法

        <bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
            <!--配置当前类中相应的属性-->  
            <property name="springDao" ref="springDao"></property>  
        </bean>  
    <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>  
    
    

    构造注入

    注入带参数构造函数的bean

        <bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
            <!--创建构造器注入,如果主类有带参的构造方法则需添加此配置-->  
            <constructor-arg ref="springDao"></constructor-arg>  
            <constructor-arg ref="user"></constructor-arg>  
        </bean>  
            <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>  
             <bean name="user" class="com.bless.springdemo.vo.User"></bean>  
    

    静态工厂的方法注入

    通过调用静态工厂的方法来获取自己需要的对象

        <bean name="springAction" class="com.bless.springdemo.action.SpringAction" >  
            <!--(3)使用静态工厂的方法注入对象,对应下面的配置文件(3)-->  
            <property name="staticFactoryDao" ref="staticFactoryDao"></property>  
                    </property>  
        </bean>  
        <!--此处获取对象的方式是从工厂类中获取静态方法-->  
        <bean name="staticFactoryDao" class="com.bless.springdemo.factory.DaoFactory" factory-method="getStaticFactoryDaoImpl"></bean>  
    
    

    实例工厂的方法注入

    获取对象实例的方法不是静态的,所以你需要首先new工厂类,再调用普通的实例方法

        <bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
            <!--(4)使用实例工厂的方法注入对象,对应下面的配置文件(4)-->  
            <property name="factoryDao" ref="factoryDao"></property>  
        </bean>  
          
        <!--此处获取对象的方式是从工厂类中获取实例方法-->  
        <bean name="daoFactory" class="com.bless.springdemo.factory.DaoFactory"></bean>  
        <bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean> 
    
    

    bean的作用域

    分别为singleton、prototype、request、session、global session
    bean的作用域由scope属性设置,默认singleton

    单例:singleton

    每个容器只存在一份

    prototype

    每次向ioc容器获取bean时创建新的实例

    request

    每次http请求创建一个实例且仅在当前request内有效

    session

    该属性仅用于HTTP Session,同一个Session共享一个Bean实例。不同Session使用不同的实例。

    global session

    该属性仅用于HTTP Session,同session作用域不同的是,所有的Session共享一个Bean实例

    bean的生命周期

    定义、初始化、使用、销毁

    定义

    通过构造器或工厂方法创建Bean实例,为Bean的属性设置值或对其它Bean的引用

    初始化

    调用bean初始化方法

    使用

    用户从spring ioc容器中获取实例并使用

    销毁

    调用bean销毁方法

        <!--方式1:xml配置init-method属性和destory-method属性,执行bean对于的init和destory方法-->
        <bean id="person" class="com.test.Person" init-method="init" destroy-method="destory">
            <property name="name" value="xujian"></property>
            <property name="age" value="23"></property>
            <property name="sex" value="男"></property>
        </bean>
    
    public class TestInitializingBean implements InitializingBean,DisposableBean{
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("run InitializingBean");        
        }
    
        @Override
        public void destory() throws Exception {
            System.out.println("run destory");        
        }
    }
    

    注解

    类的自动检测

    <!--检测类并注册bean,context:component-scan包含了context:annotation-config-->
    <context:component-scan base-package="com.xyg.pojo"></context:component-scan>
    

    作用域:@Scope

    @Component
    @Scope("prototype")
    public class AnnotationTest {
    
        private int age;
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public void getName(){
            System.out.println("调用方法");
        }
    
    
    }
    

    自动装配:@AutoWired

    //setter注入
    @Component
    public class AutoService {
    	
    	AutoDao autoDao;
    
    	@Autowired
    	public void setAutoDao(AutoDao autoDao) {
    		this.autoDao = autoDao;
    	}
    	
    	public void say(String message){
    		autoDao.say(message);
    	}
    }
    //成员注入
    @Component
    public class AutoService {
    	@Autowired
    	AutoDao autoDao;
    	
    	public void say(String message){
    		autoDao.say(message);
    	}
    }
    

    @Qualifier

    按类型装配可能有多个bean实例情况,可使用Qualifier缩小范围

    @Service("service")
    public class EmployeeServiceImpl implements EmployeeService {
        public EmployeeDto getEmployeeById(Long id) {
            return new EmployeeDto();
        }
    }
    
    @Service("service1")
    public class EmployeeServiceImpl1 implements EmployeeService {
        public EmployeeDto getEmployeeById(Long id) {
            return new EmployeeDto();
        }
    }
    
    //成员上的Qualifier
    public class EmployeeInfoControl {
        
        @Autowired
        @Qualifier("service")
        EmployeeService employeeService;
    }
    

    @Bean

    @Bean是一个方法级别上的注解,主要用在@Configuration注解的类里,也可以用在@Component注解的类里。添加的bean的id为方法名

    定义一个bean

    @Configuration
    public class AppConfig {
    
        @Bean
        public TransferService transferService() {
            return new TransferServiceImpl();
        }
    
    }
    

    等价于

    <beans>
        <bean id="transferService" class="com.acme.TransferServiceImpl"/>
    </beans>
    

    自定义bean的命名

    默认情况下bean的名称和方法名称相同,你也可以使用name属性来指定

    @Configuration
    public class AppConfig {
    
        @Bean(name = "myFoo")
        public Foo foo() {
            return new Foo();
        }
    
    }
    

    接受生命周期的回调

    public class Foo {
        public void init() {
            // 初始化逻辑
        }
    }
    
    public class Bar {
        public void cleanup() {
            // 销毁逻辑
        }
    }
    
    @Configuration
    public class AppConfig {
    
        @Bean(initMethod = "init")
        public Foo foo() {
            return new Foo();
        }
    
        @Bean(destroyMethod = "cleanup")
        public Bar bar() {
            return new Bar();
        }
    
    }
    

    AOP面向切面编程

    https://www.imooc.com/video/15678

    概念

    是一种编程范式(其他变成范式:面向过程、面向函数)

    目的

    DRY:解决代码重复问题
    SOC:关注点分离

    Spring AOP注解

    @Aspect

    表示该类是一个切面的配置类

    @pointcut

    表示那些类那些方法上来植入代码,由切面表达式组成

    @Pointcut("@annotation(AdminOnly)")
    public void adminOnly(){
    }
    

    Advice

    包括@Before,@After等,表示在方法的之前/之后进行代码的植入

    切面表达式

    格式:@Pointcut("切入点表达式"),方法体通常是空的。

    匹配包/类型

    @Pointcut("within(com.xyg.Service.UserService)")
    public void matchType(){}
    

    匹配对象

      @Pointcut("this(com.xyg.DemoDao)")
       public void thisDemo(){}//匹配指定类型的方法
      
      @Pointcut("target(com.xyg.IDao)")
       public void targetDemo(){}//匹配接口
    
       @Pointcut("bean(*Service)")
       public void BeanDemo(){}//匹配以Service结尾的Bean
    

    execution表达式

    1、execution(): 表达式主体。
    2、第一个号:表示返回类型,号表示所有的类型。
    3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法。
    4、第二个号:表示类名,号表示所有的类。
    5、(..):最后这个星号表示方法名,号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。

    例子

    @Component
    public class AdviceDao {
    	public void say(){
    		System.out.println("原始方法");
    	}
    }
     
    @Aspect
    @Component
    public class AdviceTest {
    	
    	//前置切点,值可以切点引用,也可以直接写切点表达式
    	@Before("execution(* com.how2java.dao.AdviceDao.*(..))")
    	public void before(){
    		System.out.println("前置通知。。。。。");
    	}
    	
    	@Around("execution(* com.how2java.dao.AdviceDao.*(..))")
    	public void around(ProceedingJoinPoint point) throws Throwable{
    		System.out.println("环绕通知前。。。。");
    		point.proceed();
    		System.out.println("环绕通知后。。。。");
    	}
    	
    	@AfterReturning("execution(* com.how2java.dao.AdviceDao.*(..))")
    	public void after(){
    		System.out.println("后置通知。。。。。");
    	}
    }
    

    对应的xml表示

        <!-- 开启对aop注解的支持 -->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
        <!--声明aop配置-->
        <aop:config>
        	<aop:pointcut expression="execution(* com.how2java.dao.AdviceDao.*(..))" id="advicePoint"/>
        	
            <!--定义通知类型-->
        	<aop:aspect id="adviceAspect" ref="advice">
        		<aop:after-returning method="after" pointcut-ref="advicePoint"/>
        		<aop:around method="around" pointcut-ref="advicePoint"/>
        		<aop:before method="before" pointcut-ref="advicePoint"/>
        	</aop:aspect>
        </aop:config>	
    

    Spring对代理模式的选择

    如果目标对象实现了接口用JDK动态代理,没有实现接口用cglib进行动态代理,如果实现了接口且强制cglib代理,则使用cglib代理。


    springMVC原理

    客户端发送请求-> 前端控制器 DispatcherServlet 接受客户端请求 -> 找到处理器映射 HandlerMapping 解析请求对应的 Handler-> HandlerAdapter 会根据 Handler 来调用真正的处理器开处理请求,并处理相应的业务逻辑 -> 处理器返回一个模型视图 ModelAndView -> 视图解析器进行解析 -> 返回一个视图对象->前端控制器 DispatcherServlet 渲染数据(Moder)->将得到视图对象返回给用户

    版本2: SpringMVC是Spring中的模块,它实现了mvc设计模式的web框架,首先用户发出请求,请求到达SpringMVC的前端控制器(DispatcherServlet),前端控制器根据用户的url请求处理器映射器查找匹配该url的handler,并返回一个执行链,前端控制器再请求处理器适配器调用相应的handler进行处理并返回给前端控制器一个modelAndView,前端控制器再请求视图解析器对返回的逻辑视图进行解析,最后前端控制器将返回的视图进行渲染并把数据装入到request域,返回给用户。
    DispatcherServlet作为springMVC的前端控制器,负责接收用户的请求并根据用户的请求返回相应的视图给用户。


    spring事务

    参考

    事务隔离级别

    隔离级别 含义
    DEFAULT 使用后端数据库默认的隔离级别(spring中的默认选择项)
    READ_UNCOMMITED 允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读
    READ_COMMITTED 允许在并发事务已经提交后读取。可防止脏读,但幻读和 不可重复读仍可发生
    REPEATABLE_READ 对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生。
    SERIALIZABLE 完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的。

    Mysql 默认隔离级别 REPEATABLE_READ,Oracle 默认隔离级别 READ_COMMITTED

    事务的传播行为

    当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。Spring定义了七种传播行为:

    传播行为 含义
    PROPAGATION_REQUIRED 表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务
    PROPAGATION_REQUIRED_NEW 表示当前方法必须运行在它自己的事务中。一个新的事务将被启动。如果存在当前事务,在该方法执行期间,当前事务会被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
    PROPAGATION_SUPPORTS 表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行
    PROPAGATION_NOT_SUPPORTED 表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
    PROPAGATION_MANDATORY 表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常
    PROPAGATION_NEVER 表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则会抛出异常
    PROPAGATION_NESTED 表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与PROPAGATION_REQUIRED一样。注意各厂商对这种传播行为的支持是有所差异的。可以参考资源管理器的文档来确认它们是否支持嵌套事务

    主要分3大类

    1)PROPAGATION_REQUIRED(默认值)、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORY
    支持当前事务, A调用B,如果A事务存在,B和A处于同一个事务 。
    事务默认传播行为 REQUIRED。最常用的。
    2)PROPAGATION_REQUIRES_NEW、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER
    不会支持原来的事务 ,A调用B, 如果A事务存在, B肯定不会和A处于同一个事务。
    常用的事务传播行为:PROPAGATION_REQUIRES_NEW
    3) PROPAGATION_NESTED
    嵌套事务 ,只对DataSourceTransactionManager有效 ,底层使用JDBC的SavePoint机制,允许在同一个事务设置保存点,回滚保存点

    【面试题】REQUIRED、REQUIRES_NEW、NESTED 区分
    REQUIRED:只有一个事务(默认,推荐)
    REQUIRES_NEW:存在两个事务,如果事务存在,挂起事务,重新又开启了一个新的事务
    NESTED:嵌套事务,事务可以设置保存点,回滚到保存点 ,选择提交或者回滚

  • 相关阅读:
    本地项目上传至GitHub
    博客园上传markdown格式文章
    Spring boot快速入门
    洛谷P1279 字串距离
    洛谷P2758 编辑距离
    POJ 堆栈基本操作
    洛谷P2815 IPv6地址压缩
    喵的Unity游戏开发之路
    喵的Unity游戏开发之路
    喵的Unity游戏开发之路
  • 原文地址:https://www.cnblogs.com/xiongyungang/p/10480422.html
Copyright © 2020-2023  润新知