Spring 笔记

PS C:\Users\sw> ls env:classpath

Name                           Value
----                           -----
CLASSPATH                      .;C:\Dev\Java\jdk1.8.0_171/lib/dt.jar;C:\Dev\Java\jdk1.8.0_171/lib/tools.jar

dt.jar  根据 Sun公司定义,把swing用来供给IDE描述 BeanInfo  => 由此引入 Spring 一个极为关键的东西 java.beans.PropertyEditor

 

 

 =================================  Ioc 容器 和 依赖注入 =========================

Dependency Injection 是后来 matiin flower 给 IoC 起的一个名字。DI是一种具体实现方式。

 

Ioc容器的作用举例说明,假设有一个 Sevice 层的类要调用 DAO 层的类  ==   该 Service 层的类  依赖了  DAO 层的类,

此时IoC容器通过【xml配置】或者【注解】方式   配置这种依赖关系。

 

依赖注入的方式有两种  构造注入 和  setter注入。

=============================   Bean 装配      ===================================================

作用域   Scope :Singleton        Prototype(每次都创建新的实例)        Request    Session  基于portlet的Session

生命周期 LifeCycle:实现 InitializeBean DisposableBean ,比 xml 早一点。(afterPropertyiesSet   start   destroy  stop )

Aware后缀的接口获取相应的资源:【ApplicationContext】Aware 【BeanNameContext】Aware

自动装配 AutoWiring :配置项 defautl-autowried="byType | byName | constructor"

ResourceLoader:【默认:跟随 context 路径资源】【classpath:资源】【file:资源】【url:资源】

public class GetResource implements ApplicationContextAware{
   private ApplicationContext actx;
    public void setApplicationContext(ApplicationContext actx){
       this.actx = actx;  
   }
    public static void main(Stirng[] args){
        actx.getResource("classpath:readme.txt");
        //...
   }
}

 

========================       使用注解方式装配 bean ======================================

<context:annotation-config / > 查找同一个 ApplicationContext 中的 bean 注解。

<context:component-scan />  包含 <context:annotation-config / > ,可以扫 @Component @Repository @Service @Controller

 

xml配置可以改变自动扫描行为

<context:component-scan base-package="org.example">
    <!-- 扫 Stub  -->
    <context:include-filter type="regex" expression=".*Stub.*Repository" />
    <!-- 忽略@Repository  -->
    <context:exclude-filter type="annotation"
    expression="org.springframework.stereotype.Repostory" />
</context:component-scan>

 

注解方式定义Bean (Id、Scope、

BeanNameGenerator | ScopeMetadataResolver | ...


@Scope("prototype")
@Service
("myService") public class MyServiceImpl implements MyService{ }

 

 
【@Autowired注解】本身是BeanPostProcessor处理,所以不能在自定义的BeanPostProcessor或自定义的BeanFactoryPostProcessor使用。

因为 @Autowired(required=true) 用在构造器上只允许一个。可以通过 @Required 达到同样的效果。

 

可以通过 @Autowried 获取 ApplicationContext 资源(Environment、ResourceLoader),而不需要实现 ApplicationContextAware。

 

获取多个 Bean

可以通过@Autowired 获取所有相同类型的实例 装配到 List 或别的集合,@Order(value="1")可以为集合元素指定顺序。

可以通过@Qualifier 限定缩小范围,获取多个Bean中指定的 Bean。

 

===================         @Configuration  Java Config        ====================

@Bean 指定创建对象名字、initMethod、destroyMethod

@ImportResource @Value          ==           <context:property-placeholder location=...>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

===========================     AOP  预编译 运行期动态代理 ===========================

程序功能统一维护:日志记录、性能统计、安全控制、事务处理、异常处理

预编译 :AspectJ 完整的AOP 

运行期动态代理 (JDK动态代理,CGLib动态代理): Spring AOP、JBoss AOP

 

pointcut + advice

<aop:config>
    <aop:aspect id="aspectName" ref="beanName">
        <aop:pointcut id="pointcutName" expression="" />
        <aop:before method="before" pointcut-ref="pointCutName" />
        <aop:after-returning method="afterReturning" pointcut-ref="pointCutName"/>
        <aop:after-throwing method="afterThrowing" pointcut-ref="pointCutName" />
        <aop:after method="afterFinally" pointcut-ref="pointCutName" />
    </aop:aspect>
</aop:config>

 

=============================== 面向 AOP 编程 =================== 

Soc Seperate on Concern   关注点分离,比如业务和非业务分离开。

权限控制  缓存控制 事务控制 审计日志 性能监控 分布式追踪 异常处理。

 

硬编码  ==  代码侵入性。怎么办?用@Aspect =  @Pointcut + Advice(@Before @Atfer(finally) @AfterReturn @AfterThrowing @Around(所有))

 

切点表达式   

① execution【 方法】、@target @args @ within @annoation 【注解】 、within 【包或类型】、this() bean() target() 【对象】、args() 【参数】

② * 任意数量字符   、+ 指定的类及子类、 .. 指定子包或参数

 

within【包或类型】常用于 限定一下类型 限定一下包

//匹配类型下所有方法
@Pointcut("within(com.example.Sample)")
//匹配包下所有类的方法 @Pointcut("within(com.example.*)")

 

 

 this() bean() target() 【对象】

 

@Pointcut("this("com.example.Demo")")//实现IDAO接口对象方法     
@Pointcut("target(com.example.IDAO)")@Pointcut("bean(*Service)")

 

args() 【参数】

@Pointcut("execution(* *..find*(Long))")@Pointcut("args(Long)")

 

@target @args @ within @annoation 【注解】

@Pointcut("@annoation("com.example.AdminOnly")")


//RetentionPolicy要为CLASS
@Pointcut("@within("com.example.AdminOnly")")

//RetentionPolicy要为RUNTIME
@Pointcut("@target("com.example.AdminOnly")")


//传参的地方 有@AdminOnly注解
@Pointcut("@args("com.example.AdminOnly")")

 

execution【 方法】{ * 任意数量字符   、+ 指定的类及子类、 .. 指定子包或参数}

execution{

     modifier-pattern ?可省

     returnType-pattern

     declaringType-pattern?可省

     name(param)

     throws ?可省

}

@Pointcut("execution(public * com.example.*Service.*(..))")

//加两个.. 匹配到子包
@Pointcut("execution(public * com.example..*Service.*(..))")

 

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  通知    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

// @Around = @Before + @After*
// 需要把 接入点再传出去
@Around("切点方法名")
public Object do(ProceedingJoinPoint joinPoint){
    // before
    Object result = null
    try{
        result = joinPoint.proceeding(joinPoint.getArgs());
        // afterReturning 
    }catch (Throwable t) {
        // afterThrow
    } finally{
        //after(finally)
    }
} 

 

获取参数

@Before("切点方法名&&args(参数名)")
@After*("切点方法名&&args(参数名)")

 

=================================================         AOP 原理就是 =====================================

【静态接口代理模式】。Proxy 负责在具体方法连接点(before、after*),Target仍然负责具体方法逻辑。

【jdk动态接口代理】底层原理使用反射生成  接口实现方法,优点 直接代理掉 一个类的所有方法(现有、未来新增的)

public class JdkProxy implements InvocationHandler{

    private Subject subject;
    
    public JdkProxy(Subject subject) {
        this.subject = subject;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before print");
        Object result = null;
        try {
            result = method.invoke(subject, args);
            System.out.println("afterReturn print");
        } catch (Exception e) {
            System.out.println("afterThrow print");
            throw e;
        }finally {
            System.out.println("after print");
        }
        return result;
    }
}

public class Client {

    public static void main(String[] args) {
        Subject subject = (Subject) java.lang.reflect.Proxy.newProxyInstance(Client.class.getClassLoader(), 
                new Class[] {Subject.class}, new JdkProxy(new SubjectImpl()));
        subject.request();
    }

}

 【cgLib 继承代理】

static class CGLibMIntercepter implements MethodIntercepter{
@Override
public Object intercept(Object obj,Method method,Object[] args,MethodProxy proxy)throw Throwable{
        //关键方法
Object result = proxy.invokeSuper(obj,args);
}

}

public static void main(String[] args){
Subject subject = getProxy(Subject.class,new CGLibMIntercepter());
subject.request();
}

public
static Object getProxy(Class clz,MethodIntercepter intercepter){ Enhancer enhancer = new Enhancer(); enhancer.setSuperClass(clz); enhancer.setCallback(intercepter); return enhancer.create(); }

 

JDK与Cglib代理对比:

1:JDK只能针对有接口的类的接口方法进行动态代理;

2:Cglib基于继承来实现代理,无法对static、final类进行代理;

3:Cglib基于继承来实现代理,无法对private、static方法进行代理。

 

Spring 对于两种实现方式都支持配置!DefaultAopProxyFactory 比如接口用JDK动态代理,是继承用CgLib代理。(PS:Spring源码好复杂。。。还是掌握简单的理解概念就好。)

 【配置】@EnableAspectJAutoProxy(proxyTargetClass = true) 强制使用 CgLib 代理。

 

 

 AOP 怎么链式调用起来?使用了责任链模式。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

=============================   事务管理  ====================================

AtomicityConsistencyIsolationDuralbility   ==  ACID == 原子性(最小不可分割操作单位)、一致性(前后状态)、隔离性(并发事务之间)、持久性(写入记录)

经典例子  转账。【事务回滚】

 

【PlatformTransactionManager 事务管理器】Platform 指的是   iBatis Hibernate  JPA 具体实现。

 

【TransactionDefinition  事务定义信息(隔离 传播 超时 只读)】

【DEFAULT】mysql _ REPEATABLE_READ   

【READ_UNCOMMITED】不隔离问题  脏读、不可重复读、幻读

【READ_COMMITED】【脏读】一个事务读取另一个事务改写还没提交的数据,没提交如果回滚,读到的数据是无效的。

【REPEATABLE_READ】【不可重复读】一个事务下,多次读取数据,得到不同结果,

【SERIALIZABLE】【幻读】一个事务在执行读取的时候,被插入另一个事务记录。

 

传播  

【目的 支持当前事务】

    【传播当前事务,没有要传播的事务】支持传并创建、支持传但不创建、不传就抛异常      PROPAGATION_ ( REQUIRED、SUPPORTS、MANDATORY )  

【让事务分开】

    【传播当前事务,有要传播的事务】另外创建、挂起当前但不支持传、拒绝且抛异常】PROPAGATION_ ( REQUIRED_NEW、NOT_SUPPORTED、NEVER )

【让事务嵌套执行     利用保存点回滚】

PROPAGATION_NESTED

 

【TransactionStatus    】

 是否有保存点 等状态

 

---------------------------------------------------------------------------  PlatformTransactionManager、CombopooledDataSource 事务的使用  ===========================

编程式使用事务  TransactionTemplate

声明式使用事务 AOP     

  1种  TransactionProxyBean   

<bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
           <!-- 配置目标对象 -->
           <property name="target" ref="accountService"/>
           
           <!-- 注入事务管理器 -->
           <property name="transactionManager" ref="transactionManager"/>
           
           <!-- 注入事务属性 -->
           <property name="transactionAttributes">
              <props>
                  <!-- PROPAGATION_REQUIRED:支持当前事务,如果不存在就新建一个事务 -->
                  <!-- 
                       prop的格式:
                       * PROPAGATION   事务的传播行为
                       * ISOLATION     事务的隔离级别
                       * readOnly      只读(不可进行修改)
                       * -Exception    发生哪些异常回滚事务
                       * +Exception    发生哪些异常事务不回滚
                   -->
                  <prop key="具体方法或通配符">PROPAGATION_REQUIRED</prop>
              </props>
           </property>

</bean>

 

  2种 AspectJ    只要调用到 AccountService的所有方法,都会启动通知。

<!-- 配置事务的通知 -->
  <tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
      <tx:method name="transfer" propagation="REQUIRED"/>
    </tx:attributes>
  </tx:advice>

  <!-- 配置切面 -->
  <aop:config>
    <!-- 配置切入点 -->
    <aop:pointcut expression="execution(* com.demo3.AccountService.*(..))" id="pointcut1"/>
    <!-- 配置切面 -->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
  </aop:config>

 

      3种 @Transactional

  <!-- 开启注解事务 -->
  <tx:annotation-driven transaction-manager="transactionManager"/>

在对应需要事务管理的业务层上加上注解

@Transactional

 

posted @ 2018-07-12 14:21  chenhui7373  阅读(210)  评论(0编辑  收藏  举报