Spring框架_代理模式(静态代理,动态代理,cglib代理)
共性问题:
1. 服务器启动报错,什么原因?
* jar包缺少、jar包冲突
1) 先检查项目中是否缺少jar包引用
2) 服务器: 检查jar包有没有发布到服务器下;
用户库jar包,需要手动发布到tomcat. (每次新建项目)
3) 重新发布项目
* 配置文件错误
(web.xml / struts.xml /bean.xml /hibernate.xml / *.hbm.xml)
明确的提示
* 端口占用
* webapps项目过多
当前项目没有问题,有可能是其他项目出错,这样启动也会报错!但这个错误不是当前错误报的,所以不影响当前项目运行.
注意:一般开发中,一个tomcat下只有一个项目。
2. 一般启动报错: ClassNotFoundException异常,少jar包。
3. 访问404,什么原因?
1)客户端路径写错,或跳转错误。
2)启动报错
Web项目中,启动后一定要看下,是否报错。
4. 点击某个功能报错。
后台代码错误:
à 找到页面,点击哪个操作,提交到哪个地址
--》后台在提交地址的第一行打断点
Spring提供了一站式解决方案:
1) Spring Core spring的核心功能: IOC容器, 解决对象创建及依赖关系
2) Spring Web Spring对web模块的支持。
可以与struts整合,让struts的action创建交给spring
spring mvc模式
3) Spring DAO Spring 对jdbc操作的支持 【JdbcTemplate模板工具类】
4) Spring ORM spring对orm的支持:
既可以与hibernate整合,【session】
也可以使用spring的对hibernate操作的封装
5)Spring AOP 切面编程
6)SpringEE spring 对javaEE其他模块的支持
目标:
1) 代理模式
静态代理
动态代理
Cglib代理
2)手动实现AOP编程 【代理模式】
3)AOP编程
* 注解方式实现
* XMl配置方式实现
4) Spring DAO
Spring对jdbc操作的支持
1. 代理模式
1.1 概述
代理(Proxy)是一种设计模式, 提供了对目标对象另外的访问方式;即通过代理访问目标对象。 这样好处: 可以在目标对象实现的基础上,增强额外的功能操作。(扩展目标对象的功能)。
举例:明星(邓紫棋)<---经纪人<-------用户
目标 (代理)

代理模式的关键点: 代理对象与目标对象。
1.2 静态代理
静态代理: 代理对象,要实现与目标对象一样的接口;
举例: 保存用户(模拟)
Dao , 直接保存
DaoProxy, 给保存方法添加事务处理
IUserDao
// 接口
public interface IUserDao {
void save();
}
UserDao:只执行保存数据功能,并不增加事物功能
/**
* 目标对象
*/
public class UserDao implements IUserDao{
@Override
public void save() {
System.out.println("-----已经保存数据!!!------");
}
}
UserDaoProxy:代理对象增强了目标对象UserDao功能,增加了事务功能
/**
* 代理对象(静态代理)
* 代理对象,要实现与目标对象一样的接口
*/
public class UserDaoProxy implements IUserDao{
// 接收保存目标对象
private IUserDao target;
public UserDaoProxy(IUserDao target) {
this.target = target;
}
@Override
public void save() {
System.out.println("开始事务...");
target.save(); // 执行目标对象的方法
System.out.println("提交事务...");
}
}
测试类:
public class App {
public static void main(String[] args) {
// 目标对象
IUserDao target = new UserDao();
// 代理
IUserDao proxy = new UserDaoProxy(target);
proxy.save(); // 执行的是,代理的方法
}
}
总结静态代理:
好处:可以做到在不修改目标对象的功能前提下,对目标对象功能扩展。
缺点:因为代理对象,需要与目标对象实现一样的接口。所以会有很多代理类,类太多。
一旦接口增加方法,目标对象与代理对象都要维护。
解决静态代理缺点的方法:代理工厂,也可以使用动态代理。
1.3 动态代理
动态代理,
1)代理对象,不需要实现接口;
2)代理对象的生成,是利用JDKAPI, 动态的在内存中构建代理对象(需要我们指定创建 代理对象/目标对象 实现的接口的类型;);
3) 动态代理也叫JDK代理或者 接口代理;
JDK中生成代理对象的API: java.lang.reflect.Proxy 反射包下面
|-- Proxy
static Object newProxyInstance( 产生代理对象实例的方法
ClassLoader loader, 指定当前目标对象使用类加载器
Class<?>[] interfaces, 目标对象实现的接口的类型
InvocationHandler h 事件处理器
)
使用动态代理,接口及目标对象都不用变,只需要动态的创建代理对象
/**
* 给所有的dao创建代理对象【动态代理】 静态代理,需要为每个dao都要单独的创建代理对象。
*
* 代理对象,不需要实现接口
*/
public class ProxyFactory {
// 维护一个目标对象
private Object target;
public ProxyFactory(Object target){ //这里使用Object,因为他要创建所有的动态代理对象,或者这里使用泛型也可以。
this.target = target;
}
// 给目标对象,生成代理对象
public Object getProxyInstance() {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(), //当前目标对象的类加载器
target.getClass().getInterfaces(), //目标对象实现的接口类型
new InvocationHandler() { //事件处理器
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("开启事务");
// 执行目标对象方法
Object returnValue = method.invoke(target, args);
System.out.println("提交事务");
return returnValue;
}
});
}
}
测试类:
public class App {
public static void main(String[] args) {
// 目标对象
IUserDao target = new UserDao();
// 【原始的类型 class cn.itcast.b_dynamic.UserDao】
System.out.println(target.getClass());
// 给目标对象,创建代理对象
IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance(); 这里使用了接口来接收代理对象,所以目标对象一定要实现接口,
否则不能使用动态代理
// class $Proxy0 内存中动态生成的代理对象
System.out.println(proxy.getClass());
// 执行方法 【代理对象】
proxy.save();
}
}
动态代理总结:
代理对象不需要实现接口,但是目标对象一定要实现接口;否则不能用动态代理!
(class $Proxy0
implements IuserDao)
思考:
有一个目标对象,想要功能扩展,但目标对象没有实现接口,怎样功能扩展?
Class UserDao{}
//
子类的方式
Class
subclass extends UserDao{}
以子类的方式实现(cglib代理)
1.4 Cglib代理
Cglib代理,也叫做子类代理。在内存中构建一个子类对象从而实现对目标对象功能的扩展。
JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的类,就可以使用CGLIB实现。
CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)。
CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。
Cglib子类代理:
1) 需要引入cglib – jar文件, 但是spring的核心包中已经包括了cglib功能,所以直接引入spring-core-3.2.5.jar即可。
2)引入功能包后,就可以在内存中动态构建子类
3)代理的类不能为final, 否则报错。
4) 目标对象的方法如果为final/static, 那么就不会被拦截,即不会执行目标对象额外的业务方法。
/**
* 目标对象,没有实现接口,不能使用动态代理,要使用cglib代理
*/
public class UserDao {
public void save() {
System.out.println("-----已经保存数据!!!------");
}
}
/**
* Cglib子类代理工厂
* (对UserDao 在内存中动态构建一个子类对象)
*/
public class ProxyFactory implements MethodInterceptor{
// 维护目标对象
private Object target;
public ProxyFactory(Object target){
this.target = target;
}
// 给目标对象创建代理对象
public Object getProxyInstance(){
//1. 工具类
Enhancer en = new Enhancer();
//2. 设置父类
en.setSuperclass(target.getClass());
//3. 设置回调函数
en.setCallback(this);
//4. 创建子类(代理对象)
return en.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("开始事务.....");
// 执行目标对象的方法
Object returnValue = method.invoke(target, args);
System.out.println("提交事务.....");
return returnValue;
}
}
测试类:
public class App {
public static void main(String[] args) {
// 目标对象
UserDao target = new UserDao();
// class cn.itcast.c_cglib.UserDao
System.out.println(target.getClass());
// 代理对象
UserDao proxy = (UserDao) new ProxyFactory(target).getProxyInstance();
// UserDao子类:class cn.itcast.c_cglib.UserDao$$EnhancerByCGLIB$$25d4aeab
System.out.println(proxy.getClass());
// 执行代理对象的方法
proxy.save();
}
}
在Spring的AOP编程中,
如果加入容器的目标对象有实现接口,用JDK代理;
如果目标对象没有实现接口,用Cglib代理;
Spring框架_代理模式(静态代理,动态代理,cglib代理)的更多相关文章
- spring AOP 代理(静态与动态+使用cglib实现)
一.没有代理模式 缺点: 1.工作量特别大,如果项目中有多个类,多个方法,则要修改多次. 2.违背了设计原则:开闭原则(OCP),对扩展开放,对修改关闭,而为了增加功能把每个方法都修改了,也不便于维护 ...
- 分享知识-快乐自己:三种代理(静态、JDK、CGlib 代理)
1):代理模式(静态代理)点我下载三种模式源码 代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理. 静态代理由 业务实现类.业务代理类 两部分组成 ...
- Spring代理模式(jdk动态代理模式)
有动态代理和静态代理: 静态代理就是普通的Java继承调用方法. Spring有俩种动态代理模式:jdk动态代理模式 和 CGLIB动态代理 jdk动态代理模式: 代码实现: 房东出租房子的方法(继承 ...
- 代理模式及jdk动态代理原理
代理模式 :为其它对象提供代理,以控制对这个对象的访问. 代理模式的特征:代理类(proxyClass)与委托类(realClass)有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转 ...
- java 设计模式之单利模式以及代理模式(静态)
1:单利模式: public class Singleton { private static Singleton uniqueInstance = null; private Singleton() ...
- Java代理模式/静态代理/动态代理
代理模式:即Proxy Pattern,常用的设计模式之一.代理模式的主要作用是为其他对象提供一种代理以控制对这个对象的访问. 代理概念 :为某个对象提供一个代理,以控制对这个对象的访问. 代理类和委 ...
- 代理模式(静态代理、JDK动态代理原理分析、CGLIB动态代理)
代理模式 代理模式是设计模式之一,为一个对象提供一个替身或者占位符以控制对这个对象的访问,它给目标对象提供一个代理对象,由代理对象控制对目标对象的访问. 那么为什么要使用代理模式呢? 1.隔离,客户端 ...
- 【Java】代处理?代理模式 - 静态代理,动态代理
>不用代理 有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码. 这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果.(至于为什么不直接用+号运算, ...
- Java中的代理模式--静态代理和动态代理本质理解
代理模式定义:为其他对象提供了一种代理以控制对这个对象的访问. 代理模式的三种角色: Subject抽象主题角色:抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求. Real ...
随机推荐
- ap143 led修改
以前的硬件版本只使用了一个eth口,新的板子增加了一个eth口,并且增加了响应的通信时使用的灯. led修改涉及到一下的内容: (1)led 对应的gpio口(这个需要根据原理图来定义) 需要修改的源 ...
- Oracle新实例创建
http://blog.itpub.net/29519108/viewspace-1443918/ 刚开始创建时,千万别点容器数据库,不然后面新建用户时,用户名前得加C##. 常用命令: sqlplu ...
- Docker 总结
版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] Docker总结 简单介绍 1 Docker 架构 安装和环境配置 1 mac 11 brew安装 11 dmg文件安装 1 ...
- Maven编译可执行jar
打包: 第一种情况:独立项目,且无第三方依赖包 这种情况下,我们需要maven的maven-jar-plugin插件来帮我们打包.请在项目pom.xml中的plugin配置处加入如下内 <plu ...
- echarts中,y轴文本倾斜
yAxis : [ { type : 'category', data : ['国家公务员','专业技术人员','职员','企业管理人员'], axisLabel:{ interval: 0 , ro ...
- python报错Could not open PYTHONSTARTUP
root@liqian-python:/pythonShare/monitor/m_server/core# pythonPython 2.7.10 (default, Oct 14 2015, 16 ...
- Android;设置TextView加粗 代码设置
我用过paint的那种方式,不好使. private void setTextBold(TextView textView) { //android中为textview动态设置字体为粗体 textVi ...
- 运算程序,计算玩判断,Y继续,重复计算,N结束
#include "stdio.h" void main() { /*定义变量,d1,d2:第一.二个数 fu:符号 p1:接收判断号Y/N p2:接收的p1赋给p1 */ int ...
- 重读The C programming Lanuage 笔记四:c预处理
C预处理器执行宏替换.条件编译以及包含指定的文件.以#开头的命令行就是与处理器的对象.这些命令行的语法独立于语言的其他部分,它们可以出现在任何地方,其作用可延续到所在编译单元的末尾(与作用域无关).行 ...
- java中String类型的相关知识
String类方法整理说明: ·Length()用来求字符串的长度,返回值为字符串的长度: ·charAt()取该字符串某个位置的字符,从0开始,为char类型: ·getChars()将这个字符串中 ...