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;}@Overridepublic void save(Employee e) {System.out.println("sessionFactory.getCurrentSession");System.out.println("session.getTranscation().begin()");target.save(e);System.out.println("session.getTranscation().commit()");}@Overridepublic 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;}@Overridepublic 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);}}
@Testpublic 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的实例;
转载于:https://www.cnblogs.com/Java0120/p/9954652.html
Spring-day02相关推荐
- spring的aop注解配置(了解)
这个演示是属于XML配置的,咱们Spring AOP还有一种,注解配置,注解这个东西就是代理配置文件的,那接着来看一下,使用注解,怎么来做,那其实步骤还是一样,包还是刚才的4+2+2,准备目标对象也还 ...
- 利用组件注解符精简Spring配置文件
文章目录 一.创建新包 二.复制四个类 三.修改杀龙任务类 四.修改救美任务类 五.修改勇敢骑士类 六.修改救美骑士类 七.创建Spring配置文件 八.创建测试类 九.程序优化 - 面向接口 1.创 ...
- Java企业开发学习笔记(1.2)利用组件注解符精简Spring配置文件
该文章主要为完成实训任务,详细实现过程及结果见[http://t.csdn.cn/iSeSH] 文章目录 一. 利用组件注解符精简Spring配置文件 1.1 创建新包 1.2 复制四个类 1.3 修 ...
- spring框架入门day02
0. 绪论 在第二天的学习中的学习JdbcTemplate之前,想要下载最新版本的mysql server8.0.11 结果在将所有的东西配置好后,发现报错, · Establishing SSL c ...
- Spring 学习笔记(day02)
文章目录 spring-day02 1 使用注解配置spring 1.1 步骤 1.2 将对象注册到容器 1.3 修改对象的作用范围 1.4 值类型注入 1.4 引用类型注入 1.5 初始化|销毁方法 ...
- Spring框架学习,day02
示例:demo7 package com.jt.demo7_anno;public interface Pet {void hello(); } package com.jt.demo7_anno;i ...
- spring学习笔记 -- day02 spring基础、IOC控制反转
一:srping的介绍 1.spring的体系结构 2.spring资源 a.spring-framework-4.2.4.RELEASE:Spring Framework的官方发行包 b.sprin ...
- Spring-学习笔记10【Spring事务控制】
Java后端 学习路线 笔记汇总表[黑马程序员] Spring-学习笔记01[Spring框架简介][day01] Spring-学习笔记02[程序间耦合] Spring-学习笔记03[Spring的 ...
- Spring-学习笔记06【Spring的新注解】
Java后端 学习路线 笔记汇总表[黑马程序员] Spring-学习笔记01[Spring框架简介][day01] Spring-学习笔记02[程序间耦合] Spring-学习笔记03[Spring的 ...
- Spring-学习笔记04【Spring的常用注解】
Java后端 学习路线 笔记汇总表[黑马程序员] Spring-学习笔记01[Spring框架简介][day01] Spring-学习笔记02[程序间耦合] Spring-学习笔记03[Spring的 ...
最新文章
- STM32之CAN---工作/测试模式浅析
- s120面板控制调速_SINAMICS S120变频调速装置
- 讲真,做Python一定不要只会一个方向!
- mysql alert on delete cascade_如何在mysql中删除级联使用?(How do I use on delete cascade in mysql?)...
- spring源码刨析总结
- [20150611]优化sql遇到问题.txt
- C# WPF MVVM开发框架Caliburn.Micro Screens, Conductors 和 Composition⑦
- 优秀!读博期间一作发10篇1区SCI,他坦言自己也曾走过弯路
- android system_server中的dump_SystemServer进程
- opencv python 生成画布_第16章 坚持一百秒(《Python趣味创意编程》教学视频)
- ScheduledExecutor定时器
- opencms使用笔记
- linux命令执行结果同行显示,Linux的watch命令 — 实时监测命令的运行结果
- 从本机复制文件到VM虚拟机出现卡死
- VoxelMorph运行时遇到的问题
- React 父组件获取子组件的方法/数据(useRef
- Android基于WIFI实现电脑和手机间数据传输的技术方案研究
- TortoiseSVN不会弹出认证(账号密码)或 TortoiseSVN正在启动版本库浏览器
- 五、肿瘤全基因组学体细胞结构突变特征(Patterns of somatic structural variation in human cancer genomes)
- 微信支付-企业付款到零钱