Spring-day02
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的更多相关文章
- Spring day02笔记
spring day01回顾 编写流程(基于xml) 1.导入jar包:4+1 --> beans/core/context/expression | commons-logging 2.编写目 ...
- 开放源代码的设计层面框架Spring——day02
spring第二天 一.基于注解的IOC配置 1.1写在最前 学习基于注解的IOC配置,大家脑海里首先得有一个认知,即注解配置和xml配置要实现的功能是 ...
- Spring day03笔记
spring day02回顾 AOP :切面编程 切面:切入点 和 通知 结合 spring aop 编程 <aop:config> 方法1: <aop:pointcut expre ...
- Spring day01笔记
struts:web层,比较简单(ValueStack值栈,拦截器) hibernate:dao层,知识点杂 spring:service层,重要,讲多少用多少 --> [了解] sprin ...
- spring框架入门day01
struts:web层,比较简单(ValueStack值栈,拦截器) hibernate:dao层,知识点杂 spring:service层,重要,讲多少用多少 --> [了解] spring ...
- Spring-Day02-依赖注入-作业
配置beans约束自动提示 spring-framework-4.2.4.RELEASE\docs\spring-framework-reference\html中打开xsd-configuratio ...
- [刘阳Java]_Spring常用注解介绍_第6讲
Spring的注解是在Spring2.5的版本中引入的,目的简化XML配置.在企业开发过程中使用注解的频率非常高,但是学习注解的前提是大家一定要对Spring基于XML配置要熟悉,这是我个人建议,因为 ...
- [刘阳Java]_Spring相关配置介绍_第5讲
这一节我们介绍一下Spring框架的相关常用配置 Spring依赖注入的两种方式(构造方法注入和setter方式注入) p-namespace方式配置 properties属性文件配置方式 集合对象配 ...
- Spring Boot 配置_yaml语法介绍 day02
一.Spring Boot 的全局配置文件(application.properties.application.yml) 1.这两种配置文件是SpringBoot 支持的对默认配置修改的格式.命名和 ...
- Spring Boot 基于Spring Initializer 的快速构建 day02
一.基于Spring Initializr 快速构建Spring Boot项目(快速) 备注:需要联网 这是使用Intellij Idea快速构建可以为我们省去大量的pom.xml配置时间,简单操作, ...
随机推荐
- [物理学与PDEs]第3章习题3电磁场的矢势在 Lorentz 规范下满足的方程
设 $\phi$ 及 ${\bf A}$ 分别为电磁场的标势及矢势 (见第一章 $\S$ 6). 试证明: 若 $\phi$ 及 ${\bf A}$ 满足条件 $$\bex \phi+\cfrac{1 ...
- 出现Failed to get convolution algorithm的解决方法
当运行卷积神经时出现了问题:Failed to get convolution algorithm. This is probably because cuDNN failed to initiali ...
- 大数据基础-2-Hadoop-1环境搭建测试
Hadoop环境搭建测试 1 安装软件 1.1 规划目录 /opt [root@host2 ~]# cd /opt [root@host2 opt]# mkdir java [root@host2 o ...
- redux知识点
1.关于传参 点击跳转 两种 动态路由 url 但是取值需要自己处理 关于动态跳转(js执行跳转) 关于异步加载组件 创建loadable app.js中 在 要加载的异步组件中 (这样接收参数不 ...
- C# - 表达式与语句
表达式与语句(Expression&Statement) 操作数(Operands) 1.数字.2.字符.3.变量.4.类型.5.对象.6.方法 操作符(Operator) 参考:C# - 操 ...
- vlan 知识学习
背景 有人反映打印机总是提示ip冲突,经检查,打印机虽然设置了固定ip,但是所有员工在路由器都是设置了DHCP,所以会存在员工占用打印机IP 情况,在路由器添加某一段的ip不自动分配解决此问题 ...
- SQL中笛卡尔积-cross join的用法
在数学中,笛卡尔乘积是指两个集合X和Y的笛卡尓积(Cartesian product),又称直积,表示为X × Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员 假设集合A={a ...
- 【原创】大数据基础之Oozie(2)使用
命令行 $ oozie help 1 导出环境变量 $ export OOZIE_URL=http://oozie_server:11000/oozie 否则都需要增加 -oozie 参数,比如 $ ...
- (转)Vue种key的作用
https://blog.csdn.net/qq_41861679/article/details/80659278 https://cn.vuejs.org/v2/api/#key 其实不只是vue ...
- JVM·垃圾收集器与内存分配策略之垃圾回收算法!
1.垃圾回收算法 1.1.标记-清除算法(Mark-Sweep): 过程分为“标记”和“清除”两个过程.先将所有需要回收的目标统一标记,然后再统一清除. ...