spring
Hibernate
1.数据持久化
2.ORM
3.使用Hibernate实现数据持久化
Struts2
1.MVC
2.使用Struts2实现MVC
3.拦截器
设计模式
1.工厂模式
2.代理模式
企业级系统
大规模:用户数量多、数据规模大、功能模块多
性能和安全要求高
业务复杂
灵活多变
Java技术如何应对
EJB---------------》Spring
侵入式 重量级的框架 EJB容器 Tomcat 只是servlet容器跑不起来 远程调用 项目庞大
Spring
轻量级JavaEE开源框架,他是由Rod Johnson为了解决企业应用程序开发的复杂性而创建
目标
实现一个全方位的整合框架,实现“一站式”的企业应用开发
内容
IOC容器
AOP实现
数据访问支持
简化JDBC/Hibernate编码
声明式事务
Web集成
Context 资源文件的加载 配置文件的加载 事件加载的
核心模块
Beans 组件 所有Java的类都有bean管理
Core
Context 上下文 事件 EJB支持
AOP增强
Spring是面向Bean的编程
IOC
AOP
Beans Core Context
Spring 两大核心技术
1.控制反转(IOC) 依赖注入(DI)
2.面向切面编程(AOP)
Action 依赖 Service 依赖 Dao
面向接口编程
将创建任务转移到容器
Repo.spring.io
Spring-framework-版本号
DTD schema 定义文档能写那些东西
<!--配置dao-->
<!--<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="cn.bdqn.dao.UserMapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<bean id="roleMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="cn.bdqn.dao.RoleMapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>-->
<!--配置service-->
<!-- <bean id="userService" class="cn.bdqn.service.impl.UserServiceImpl">
<property name="userMapper" ref="userMapper"/>
</bean>
Property给属性赋值
ApplicationContext ac=new ClassPathXmlApplicationContext("")
userService= (UserService) ac.getBean("userService");
FileSystemXmlApplicationContext 读取xml文件 系统文件的目录下
ApplicationContext 读取xml文件 src根目录下
组件化的思想:分离关注点,接口和实现分离
目的:解耦合。实现每个组件时只关注组件内部的事情
要点:明确定义组件间的接口
依赖注入:将组件的构建和使用分开
IOC使用两大关键技术 一个设计模式
1.JDOM(解析xml文件)
2.反射机制(创建实例 赋值)
3.工厂模式(单例模式)
BeanFactory
由org.springframework.beans.factory.BeanFactory
接口定义
BeanFactory是工厂模式(Factory pattern)的实现,负责创建和管理bean
BeanFactory接口包含以下基本方法
containsBean(String name) 是否包含
getBean(String name) 获得bean
getType(String name) 获得类型
ApplicationContext是BeanFactory的子接口
实现类ClassPathXmlApplicationContext
实现类FileSystemXmlApplicationContext
原型啥时候用 在创建
单例 服务启动的时候就创建
Aop(Aspect-Oriented Programming)
1.面向切面编程
2.将复杂的需求分解出不同方面,将散布在系统中的公共功能集中解决
使用“横切”技术,AOP把软件系统分为两部分
核心关注点
横切关注点
实现方法:动态代理设计模式
交叉业务
Biz 日志
权限
Dao 安全
Biz 日志
代理(运行的时候)
AOP(Aspect-Oriented Programming)
面向切面编程,是一种通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态添加功能的技术
<bean id=”testLogger” class=”logger.TestLogger”/>
<aop:config>
</aop:config>
增强:带着位置的方法
切入点:把增强放在那里 实现业务接口的类 都需要增强
连接点:具体被选中的人 具体的方法
切面: 增强和接入点的结合
代理:
目标对象:凡是得到增强的人
织入:把增强和切入点结合
AOP实现者
AspectJ
JBoss AOP
Spring AOP
Spring提供了4种实现AOP的方式
1.基于代理的经典AOP
2.纯POJO切面
3.@AspectJ注解驱动的切面
4.注入式AspectJ切面
目标方法
增强方法
切入点 <aop:pointcut >配置切面
Expression:切入表达式
Aspect:切面配置
在beforeLogger方法之前切入
把testLogger类的方法brforeLogger添加到符合切点pointcut组件的前面
Pointcut-ref 切入点 筛选条件
只有运行的时候我才知道那个方法被切入,执行的方法称为连接点
Jp.getTarget();获取目标类型
Jp.getSignature().getName();//获取方法名
Js.getArgs()[0];//获取参数列表
Returning=”result”参数的返回值 获得返回值给方法afterReturningLogger里的参数result
Jdk 动态代理面向接口
B1 B2实现类 真正的实现类有个test()方法 在这个方法中
前面执行的方法 中间执行B1 B2通过注入执行的方法
创建速度快 运行慢
Cglib动态代理 面向继承 代码生成库
通过类的可执行文件 知道你的编译规则 在内存中创建其生成业务类的子类biz 重写 父类的方法在test方法里完成增强 运行中 动态创建子类
创建时候比较慢 运行的速度快
Cjlib可以代理没有接口的代理
如果类是final不能继承 所以不能代理
如果类中的某个方法是final 所以这个方法也不能被代理
Spring 通过jdk动态代理实现的
Spring 通过cjlib动态代理实现的
Proxy-target-class=”true” 强制用cjlib.
带参构造注入
第一个函数
p:属性名 八种基本数值类型 一种String
Local:在当前的配置文件 查找id
Bean:在所有配置文件查找
集合 或者数组
集合里放入对象
Set集合
Map注入
Properties hashtable 子类
赋值为空值 空串
环绕通知 当执行环绕通知的时候 调用目标方法时她才执行 如果不调用就不执行 还可以对返回值进行修改
Jp.proceed();决定业务方法是否执行。可以对
业务方法的返回值进行修改 但是后置通知不可以修改业务的返回数据。canExec 为false 所以业务方法的不到执行
把testLogger中的方法around方法 符合pointcut切点 使用环绕通知。
如果方法传t01 业务方法得到执行
如果前置后置能搞定 就别用环绕通知 否则造成 资源浪费
异常通知
配置
总是会执行的方法
前置增强
后置增强
注解配置
@Component尽量不适用
放在构造 属性 set方法上 设值注入
@Autowired 按类型注入
配置文件base-package=“biz,dao”多个包用逗号隔开
@Qualifier(“testDao”)按名称注入
@Scope(“prototype”) 按原型模式创建
@Aspect
JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。
简单的实现举例:
这是一个需要被代理的类,也就是父类,通过字节码技术创建这个类的子类,实现动态代理。
[java] view plain copy
- public class SayHello {
- public void say(){
- System.out.println("hello everyone");
- }
- }
该类实现了创建子类的方法与代理的方法。getProxy(SuperClass.class)方法通过入参即父类的字节码,通过扩展父类的class来创建代理对象。intercept()方法拦截所有目标类方法的调用,obj表示目标类的实例,method为目标类方法的反射对象,args为方法的动态入参,proxy为代理类实例。proxy.invokeSuper(obj, args)通过代理类调用父类中的方法。
[java] view plain copy
- public class CglibProxy implements MethodInterceptor{
- private Enhancer enhancer = new Enhancer();
- public Object getProxy(Class clazz){
- //设置需要创建子类的类
- enhancer.setSuperclass(clazz);
- enhancer.setCallback(this);
- //通过字节码技术动态创建子类实例
- return enhancer.create();
- }
- //实现MethodInterceptor接口方法
- public Object intercept(Object obj, Method method, Object[] args,
- MethodProxy proxy) throws Throwable {
- System.out.println("前置代理");
- //通过代理类调用父类中的方法
- Object result = proxy.invokeSuper(obj, args);
- System.out.println("后置代理");
- return result;
- }
- }
具体实现类:
[java] view plain copy
- public class DoCGLib {
- public static void main(String[] args) {
- CglibProxy proxy = new CglibProxy();
- //通过生成子类的方式创建代理类
- SayHello proxyImp = (SayHello)proxy.getProxy(SayHello.class);
- proxyImp.say();
- }
- }
输出结果:
[plain] view plain copy
- 前置代理
- hello everyone
- 后置代理
CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理。
浙公网安备 33010602011771号