Annotation复习:
1,Annotation:作为类型的元数据;
  1,给类型加标记;
  2,annotation可以添加各种类型的属性;
2,Annotation的上的标记:
  1),target:标签可以加在什么类型上的;
    1),TYPE:所有类和接口;
    2),METHOD:方法;
    3),FIELD:字段上面;
    4),PARAMETER:方法的参数上面;
    5),CONSTRUCTOR:构造器方法;
  2),retention:把标签保留到什么时候;
    1),CLASS:保留到字节码;
    2),SOURCE:保留到代码;
    3),RUNTIME:保留到运行时;

3,标签一般需要三方参与:
  1),标签类型;
  2),打标签的目标类型;
  3),解析程序;
  4),注解的参数:
    1),注解中属性的添加方式;
    2),注解中属性的默认值;
    3),getAnnotation方法的使用;

Spring的注解使用;

DI注解的使用:
1,使用DI注解,在spring的配置文件里面还是需要配置bean本身;
2,@Autowired
  1),autowired标签可以把需要的对象自动的注入到目标对象中;
  2),autowired标签可以放在字段上,也可以放在setter方法上面;
  3),autowired的执行流程:
    1),加载和解析XML文件;
    2),实例化所有的bean,并且方到spring的容器当中;
    3),解析对象的类型,如果对象类型的某些字段或者setter方法上面有@Autowired标签,
      1),在容器中找到对应的对象;
      2),把找到的对象设置到字段或者setter方法中;
  4),怎么找对象?
    1),首先按照类型找;
    2),如果没有找到;系统报错(默认情况下,autowired标签有一个@Required标签的作用)
    3),如果找到多个,按照字段或者属性的名字,再用名字+类型去找;
    4),如果1,3都没有找到,报错;
    5),可以通过设置autowired的required=false让这个属性(字段)可以没有值;
    6),可以通过在字段或者setter方法上添加@Qualifier来规定我要注入的bean的名字;
    7),可以在Spring的主要对象上面添加@Autowired,让spring自动注入;
    8),所以,我们的spring的测试类,可以直接引用需要测试的目标对象就可以了;

3,@Resource
  1),也可以通过resource标签来自动注入;
  2),怎么找对象?
    1),首先按照字段或者属性的名字找;
    2),如果找不到,报错(resource关联的对象必须存在)
    3),如果按照名字找不到,再按照类型来找;
    4),可以通过resource的name属性来指定一个bean注入;如果一旦设置了resource的name属性,就只能按照名字找了;
    5),因为resource是javax的标签,所以resource不能注入spring中关键的对象;

选择:
1,Resource是JavaEE的规范,但是缺少spring对autowired标签的一些加强;
2,一般我们选择使用@Autowired标签;

使用IoC注解:

1,在配置文件中告诉spring去哪里扫描实例对象;

    <!--
如果要使用IOC的注解,一定要配置一个context:component-scan,
base-package表示,让Spring去扫描包及其子包下的类(是否带有IOC注解)
如果要配置多个包,包之间用逗号隔开
-->
<context:component-scan base-package="com.rk1632._03_annotation_ioc"/>

2,在类型上面添加anntation:
  1),@Component:一般我们写在工具类上面;
  2),@Service:一般我们写在服务对象上;
  3),@Repository:一般写在DAO上面;
  4),@Controller:一般写在Action上面;并且在SpringMVC中,Controller就在标示一个Controller对象;
3,这四个标签对于spring来说,作用相同,主要是给程序员看的;

<bean id="" class="" factory-method="" factory-bean="" init-method="" destory-method="" scope=""/>
1,id:所有的四个标签都支持value值,这个值就是id的名字;
2,class:不用写了;
3,factory-method和factory-bean就没有对应的标签了;如果有这种需要,直接配置到XML里面(XML和Annocation是可以混用的)
4,init-method:使用@PostConstruct直接放在init方法上面;注意:initmethod一定是在DI(依赖注入)之后执行的;
5,destory-method:使用@PreDestroy直接放在destory方法上面;
6,scope,在类上面添加@Scope("prototype");

代理模式

提出问题:
问题:事务是开在dao上面的,所以如果在service中调用多个dao的方法,如果在这些方法执行过程中报错,事务没法回滚

对于我们的应用,事务都应该开在service的方法上面

解决办法:
1,sessionFactory.getCurrentSession:得到当前线程中的session;
2,把session的开启和事务的开启,事务的提交从dao中移到service方法中

存在一个事务跨层的问题,但是如果直接把事务管理的代码写在service中,会造成service代码污染,最好的方式就是把事务的代码从service中抽取出来,使用代理模式,再加到目标代码中:

静态代理:

public class EmployeeServiceImpl implements IEmployeeService {

    public void save(Employee e) {

        System.out.println("save Employee");
} public void update(Employee e) { System.out.println("update Employee");
} }
public class EmployeeTranscationServiceImpl implements IEmployeeService {

    private IEmployeeService target;

    public EmployeeTranscationServiceImpl(IEmployeeService service){
this.target = service;
} @Override
public void save(Employee e) {
System.out.println("sessionFactory.getCurrentSession");
System.out.println("session.getTranscation().begin()");
target.save(e);
System.out.println("session.getTranscation().commit()");
} @Override
public void update(Employee e) {
System.out.println("sessionFactory.getCurrentSession");
System.out.println("session.getTranscation().begin()");
target.update(e);
System.out.println("session.getTranscation().commit()");
} }

静态代理分析:

静态代理分析:
1,静态代理确实处理了代码污染的问题;

问题:
1,重复的代码仍然分散在了各个方法中;
2,需要为每一个真实对象写一个代理对象;

Struts中的拦截器:

动态代理

1,有接口的对象的动态代理
  1),JDK中提供了针对有接口对象的动态代理实现方式;
2,没有接口的对象的动态代理
  1),使用继承的方式完成动态代理;javassist/cglib

1,客户端调用save方法,执行被InvocationHanalder拦截;
2,在invoke方法中执行添加的额外的逻辑;
3,调用m.invoke(target,args)执行到了真实的目标对象上的对应方法;
4,真实对象返回执行结果到InvocationHandler里面;
5,执行完成其他逻辑,把结果返回给客户端;

使用JDK的动态代理流程:
1,使用JDK的动态代理,必须要保证代理的真实对象是有接口的;

    /**
* proxy:代理出来的对象
* method:这次调用的方法
* args:这次调用方法传入的参数
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
}

2,需要实现一个InvocationHandler,并实现invoke方法(如上);
  0),需要给InvocationHanlder的实现类提供真实对象;
  1),在invoke方法中执行自己的额外添加的业务逻辑;
  2),在编写完额外逻辑之后,调用method.invoke(target,args)执行真实对象上的对应方法;
  3),得到真实方法执行的结果;
  4),处理结果,并把结果返回给客户端;

        //Proxy:专门用来生产代理类的对象
//newProxyInstance:需要三个参数
//1,ClassLoader():专门用来加载类的
//2,interfaces:需要接口的数组,这个接口就是我们目标对象实现的接口
//3,处理动态代理的类的对象
IEmployeeService service = (IEmployeeService)Proxy.newProxyInstance(service.getClass().getClassLoader(),
         new Class[]{IEmployeeService.class},
        new TranscationInvocationHandler(service,txManager));

3,在客户端调用Proxy.newProxyInstance方法(如上):
  1),需要传入目标对象的classloader;
  2),需要传入目标对象的接口类型;
  3),需要传入一个自定义的InvocationHandler的实例;

使用CGLIB完成没有接口的对象的动态代理

public class LogInvocationHandler implements InvocationHandler {

    private Object target;

    public LogInvocationHandler(Object target){
this.target = target;
} @Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("操作日志:操作时间:"+new Date()+", 当前调用的方法:"+method.getName()+", 传入的参数:"+Arrays.toString(args));
return method.invoke(target, args);
} }
    @Test
public void test() throws Exception {
SomeBean bean = new SomeBean(); //增强器
Enhancer enhancer = new Enhancer();
//设置目标对象的ClassLoader
enhancer.setClassLoader(bean.getClass().getClassLoader());
//设置这个动态代理的父类
enhancer.setSuperclass(SomeBean.class);
//设置要传入的拦截器
enhancer.setCallback(new LogInvocationHandler(bean));
//使用create方法创建代理对象
SomeBean o = (SomeBean) enhancer.create();
o.print1();
}

小结:
1,动态代理处理:重复的代码仍然分散在了各个方法中这个问题;
2,动态代理需要调用代码为每一个类去创建动态代理对象;
3,动态代理最小的单位就是一个类;
4,如果只想处理一个类型中的某些方法,在invoke方法中根据当前执行的方法名称去做判断就可以了;

Spring的AOP:

AOP就是一种更高级的动态代理的使用;
Aspect Oritention Programming(面向切面编程)

切入点:要加入业务逻辑的点(在哪些类的哪些方法上面;)
通知:通知包含两个方面,1,代表方法的执行时间,2,在这个时间上面要做什么事情;
切面:一个切入点+一个通知=一个切面(在什么地方,在什么时候,做什么事情);
织入:把一个切面应用到真实对象上面的过程,就叫做织入;

在Java中,没有语言能够准确的描述切入点;所以,有一个AspectJ,这是一种语言,提供了用于描述切入点的语言;

使用Spring的AOP:
1,使用XML的配置方式;
2,使用Annotation的配置方式;

定义切入点的表达式

如果可以是任意的值,使用*就可以了;

定义切入点表达式的例子如下:

aop包中,所有的service的所有的方法;
execution(* com._520it.spring.day2.aop.*Service.*(..));

day2中所有service的save方法;
execution(* com._520it.spring.day2..*Service.save(..))

    <!-- 配置AOP -->
<aop:config>
<!-- 配置一个切入点
expression:这个切入点的表达式
id:这个切入点的名称
-->
<aop:pointcut expression="execution(* com.rk1632._08_aop.*Service.*(..))" id="pc"/>
<!-- 配置一个切面
ref:代表在这个切面的定义中,所有的做什么事情,都是由txManager这个对象的方法提供的
-->
<aop:aspect ref="txManager">
<!-- before代表方法执行之前 -->
<aop:before method="begin" pointcut-ref="pc"/>
<!-- after-returning代表方法正常执行之后 -->
<aop:after-returning method="commit" pointcut-ref="pc"/>
<!-- after-throwing代表方法抛出异常的时候 -->
<aop:after-throwing method="rollback" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>

Spring中AOP的通知类型:
aop:before:前置通知;
aop:after-returning:后置通知;
aop:after:最终通知;
aop:after-throwing:异常通知;
aop:around:环绕通知;

小结:
1,准备了真实的对象,准备一个类,这个类里面的方法用来提供通知里面的做什么;

2,这两个类都要配置到Spring容器中;

3,配置springAOP
  1,引入aop命名空间;
  <aop:config>
    <aop:point-cut expression="" id="" />
    <aop:aspect ref="">
      <aop:before method="" pointcut-ref="">
      <aop:after-returning method="" pointcut-ref="">
      <aop:after-throwing method="" pointcut-ref="">
    </aop:aspect>
  </aop:config>

4,我们在客户端还是直接注入的是在spring里面配置的真实对象;
实际上,spring在为这些对象创建好代理对象之后,会使用这些创建好的代理对象去替换容器中的原始对象;

SpringAOP的执行流程:
1,解析xml;
2,实例化所有的bean;
3,解析aop:config;
  1),解析aop:aspect,得到aspect引用的对象;txManager
  2),解析aop:aspect里面的每一个切面;
    1),得到该aspect对应的pointcut-ref;
    2),得到pointcut-ref对应的pointcut的表达式;
    3),使用表达式中用于匹配类型的表达式;
    4),使用该表达式去和spring里面配置的所有的bean的类型进行匹配;
      1),如果匹配不上,不管;
      2),如果匹配上了,该对象作为spring动态代理的目标对象;
        1),如果该对象实现了接口,使用JDK的动态代理包装;
        2),如果该对象没有实现接口,使用cglib包装;
        3),得到配置的拦截时机+逻辑提供类(txManager)的对应方法(从method解析)+pointcut表达式中方法的匹配模式创建一个拦截器
        4),在把该拦截器使用对应的动态代理机制代理成代理对象;
        5),替换spring容器中的对应bean的实例;

Spring-day02的更多相关文章

  1. Spring day02笔记

    spring day01回顾 编写流程(基于xml) 1.导入jar包:4+1 --> beans/core/context/expression | commons-logging 2.编写目 ...

  2. 开放源代码的设计层面框架Spring——day02

    spring第二天     一.基于注解的IOC配置         1.1写在最前             学习基于注解的IOC配置,大家脑海里首先得有一个认知,即注解配置和xml配置要实现的功能是 ...

  3. Spring day03笔记

    spring day02回顾 AOP :切面编程 切面:切入点 和 通知 结合 spring aop 编程 <aop:config> 方法1: <aop:pointcut expre ...

  4. Spring day01笔记

    struts:web层,比较简单(ValueStack值栈,拦截器) hibernate:dao层,知识点杂 spring:service层,重要,讲多少用多少 --> [了解]   sprin ...

  5. spring框架入门day01

    struts:web层,比较简单(ValueStack值栈,拦截器) hibernate:dao层,知识点杂 spring:service层,重要,讲多少用多少  --> [了解] spring ...

  6. Spring-Day02-依赖注入-作业

    配置beans约束自动提示 spring-framework-4.2.4.RELEASE\docs\spring-framework-reference\html中打开xsd-configuratio ...

  7. [刘阳Java]_Spring常用注解介绍_第6讲

    Spring的注解是在Spring2.5的版本中引入的,目的简化XML配置.在企业开发过程中使用注解的频率非常高,但是学习注解的前提是大家一定要对Spring基于XML配置要熟悉,这是我个人建议,因为 ...

  8. [刘阳Java]_Spring相关配置介绍_第5讲

    这一节我们介绍一下Spring框架的相关常用配置 Spring依赖注入的两种方式(构造方法注入和setter方式注入) p-namespace方式配置 properties属性文件配置方式 集合对象配 ...

  9. Spring Boot 配置_yaml语法介绍 day02

    一.Spring Boot 的全局配置文件(application.properties.application.yml) 1.这两种配置文件是SpringBoot 支持的对默认配置修改的格式.命名和 ...

  10. Spring Boot 基于Spring Initializer 的快速构建 day02

    一.基于Spring Initializr 快速构建Spring Boot项目(快速) 备注:需要联网 这是使用Intellij Idea快速构建可以为我们省去大量的pom.xml配置时间,简单操作, ...

随机推荐

  1. [物理学与PDEs]第3章习题3电磁场的矢势在 Lorentz 规范下满足的方程

    设 $\phi$ 及 ${\bf A}$ 分别为电磁场的标势及矢势 (见第一章 $\S$ 6). 试证明: 若 $\phi$ 及 ${\bf A}$ 满足条件 $$\bex \phi+\cfrac{1 ...

  2. 出现Failed to get convolution algorithm的解决方法

    当运行卷积神经时出现了问题:Failed to get convolution algorithm. This is probably because cuDNN failed to initiali ...

  3. 大数据基础-2-Hadoop-1环境搭建测试

    Hadoop环境搭建测试 1 安装软件 1.1 规划目录 /opt [root@host2 ~]# cd /opt [root@host2 opt]# mkdir java [root@host2 o ...

  4. redux知识点

    1.关于传参 点击跳转 两种 动态路由 url 但是取值需要自己处理 关于动态跳转(js执行跳转) 关于异步加载组件 创建loadable app.js中 在 要加载的异步组件中   (这样接收参数不 ...

  5. C# - 表达式与语句

    表达式与语句(Expression&Statement) 操作数(Operands) 1.数字.2.字符.3.变量.4.类型.5.对象.6.方法 操作符(Operator) 参考:C# - 操 ...

  6. vlan 知识学习

    背景     有人反映打印机总是提示ip冲突,经检查,打印机虽然设置了固定ip,但是所有员工在路由器都是设置了DHCP,所以会存在员工占用打印机IP 情况,在路由器添加某一段的ip不自动分配解决此问题 ...

  7. SQL中笛卡尔积-cross join的用法

    在数学中,笛卡尔乘积是指两个集合X和Y的笛卡尓积(Cartesian product),又称直积,表示为X × Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员 假设集合A={a ...

  8. 【原创】大数据基础之Oozie(2)使用

    命令行 $ oozie help 1 导出环境变量 $ export OOZIE_URL=http://oozie_server:11000/oozie 否则都需要增加 -oozie 参数,比如 $ ...

  9. (转)Vue种key的作用

    https://blog.csdn.net/qq_41861679/article/details/80659278 https://cn.vuejs.org/v2/api/#key 其实不只是vue ...

  10. JVM·垃圾收集器与内存分配策略之垃圾回收算法!

    1.垃圾回收算法    1.1.标记-清除算法(Mark-Sweep):             过程分为“标记”和“清除”两个过程.先将所有需要回收的目标统一标记,然后再统一清除.          ...