- 浏览: 21479558 次
- 性别:
-
博客专栏
-
-
跟我学spring3
浏览量:2413738
-
-
Spring杂谈
浏览量:3004941
-
-
跟开涛学SpringMVC...
浏览量:5637070
-
-
Servlet3.1规范翻...
浏览量:259310
-
-
springmvc杂谈
浏览量:1595770
-
-
hibernate杂谈
浏览量:249843
-
-
跟我学Shiro
浏览量:5854700
-
-
跟我学Nginx+Lua开...
浏览量:700595
-
-
亿级流量网站架构核心技术
浏览量:783619
文章分类
- 全部博客 (329)
- 跟我学Nginx+Lua开发 (13)
- 跟我学spring (54)
- 跟开涛学SpringMVC (34)
- spring4 (16)
- spring杂谈 (50)
- springmvc杂谈 (22)
- 跟我学Shiro (26)
- shiro杂谈 (3)
- hibernate杂谈 (10)
- java开发常见问题分析 (36)
- 加速Java应用开发 (5)
- Servlet 3.1规范[翻译] (21)
- servlet3.x (2)
- websocket协议[翻译] (14)
- websocket规范[翻译] (1)
- java web (6)
- db (1)
- js & jquery & bootstrap (4)
- 非技术 (4)
- reminder[转载] (23)
- 跟叶子学把妹 (8)
- nginx (2)
- 架构 (19)
- flume架构与源码分析 (4)
最新评论
-
xxx不是你可以惹得:
认真看错误代码,有时候重启电脑就行了 醉了 我把数据库配置写死 ...
第十六章 综合实例——《跟我学Shiro》 -
dagger9527:
holyselina 写道您前面说到能获取调用是的参数数组,我 ...
【第六章】 AOP 之 6.6 通知参数 ——跟我学spring3 -
xxx不是你可以惹得:
Access denied for user 'root'@' ...
第十六章 综合实例——《跟我学Shiro》 -
dagger9527:
只有@AspectJ支持命名切入点,而Schema风格不支持命 ...
【第六章】 AOP 之 6.5 AspectJ切入点语法详解 ——跟我学spring3 -
dagger9527:
支持虽然会迟到,但永远不会缺席!
【第四章】 资源 之 4.3 访问Resource ——跟我学spring3
之前发过两篇关于Spring的总结帖子 反响还不错,再把剩下的几篇发上来。共享给大家。
我对IoC/DI的理解
我对AOP的理解
1、问题
1、JDBC/ORM框架(如Hibernate)开发中编程模型有哪些缺点? 如JDBC
![](http://dl.iteye.com/upload/attachment/0074/3802/5681ac78-4fd3-34c5-bc80-faaad087cc8c.jpg)
2、解决方案(模板设计模式,本质:将可变的和不可变的分离)
模板方法模式:定义操作的步骤(固定的),将可变的步骤交给子类处理。
public interface JdbcOperations { //接口定义行为集 public Object execute() throws SQLException ; }
public abstract class AbstractJdbcOperations implements JdbcOperations { @Override public final Object execute() throws SQLException { Connection conn = DataSourceUtils.getConnection(); try { Object retVal = doInConnection(conn); conn.commit(); return retVal; }catch (Exception e) { conn.rollback(); throw e;} finally { conn.close(); } } public abstract Object doInConnection(Connection conn) throws SQLException; }
public class DataSourceUtils { public static Connection getConnection() { //返回数据库连接 return null; } }
JdbcOperations select = new AbstractJdbcOperations() { @Override public Object doInConnection(Connection conn) throws SQLException { PreparedStatement pstmt = conn.prepareStatement("select * from tbl_user"); ResultSet rs = pstmt.executeQuery(); List result = null; //处理结果集 return result; } }; select.execute();
缺点:不够灵活
3、解决方案(模板设计模式+回调,本质:将可变的和不可变的分离,可变通过回调)
回调(命令):由组件定义,但不由组件调用,而是由系统调用
一般用于:可变不可变分离,未知功能。
public interface JdbcOprations2 { //接口定义行为集 public Object execute(ConnectionCallback callback) throws Exception ; }
public interface ConnectionCallback { public Object doInConnection(Connection conn) throws SQLException; }
public class JdbcTemplate implements JdbcOprations2 { @Override public Object execute(ConnectionCallback callback) throws Exception { Connection conn = DataSourceUtils.getConnection(); try { Object retVal = callback.doInConnection(conn); conn.commit(); return retVal; } catch (Exception e) { conn.rollback(); throw e; } finally { conn.close(); } } }
jdbcTemplate.execute(new ConnectionCallback() { @Override public Object doInConnection(Connection conn) throws SQLException { //可变操作 return null; } });
public interface PreparedStatementCallback { public Object doInPreparedStatement(PreparedStatement pstmt) throws SQLException; }缺点:灵活但不通用
4、解决方案(Spring JDBC框架)
![](http://dl.iteye.com/upload/attachment/0074/3810/5ed6cb77-8c01-3d8e-bff9-eb23b979f284.jpg)
JdbcTemplate jdbcTemplate = new JdbcTemplate(ds);
5、异常问题
JDBC/ORM框架(如Hibernate)开发中异常处理有哪些缺点? 不一致的异常类,如JDBC是SQLException 而hibernate是HibernateException,等。
缺点:不一致的异常体系,需要了解每个框架的异常含义 ,Spring的一致的异常体系(DataAccessException)
![](http://dl.iteye.com/upload/attachment/0074/3806/b48ed921-5f68-3beb-8c18-6d9f71ff3a87.jpg)
6、DAO访问问题
访问JDBC和访问Hibernate使用完全不同且根本不类似的API?
为了便于以一种一致的方式使用各种数据访问技术,如JDBC、JDO和Hibernate,
Spring提供了一套抽象DAO类供你扩展。
JdbcDaoSupport - JDBC数据访问对象的基类。
需要一个DataSource,同时为子类提供 JdbcTemplate。
HibernateDaoSupport - Hibernate数据访问对象的基类。
需要一个SessionFactory,同时为子类提供 HibernateTemplate。
JdoDaoSupport - JDO数据访问对象的基类。
需要设置一个PersistenceManagerFactory, 同时为子类提供JdoTemplate。
JpaDaoSupport - JPA数据访问对象的基类。
需要一个EntityManagerFactory,同时 为子类提供JpaTemplate。
一致的DAO抽象
Callback:定义可变行为,即不可预知行为(命令设计模式)
Template:提供模板支持,简化开发Support:提供对Template的支持,提供一组简便方法,并提供获取Template的方法
相关资料
评论
10 楼
jinnianshilongnian
2012-12-06
9 楼
yangpeihai
2012-12-06
yangpeihai 写道
jinnianshilongnian 写道
yangpeihai 写道
哥们,请教个问题,为什么spring使用cglib动态代理没法拦截被代理类的所有非private方法,而我自己写的由cglib生成的代理类却可以拦截到被代理类的所有非private方法呢?,先道声谢谢,下面贴代码:
1. 注解类,用来注解哪些方法需要写日志
2. 工厂类,由cglib生成被代理对象
3.被代理的类
4.测试类
5.结果输出:
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: public java.lang.String test.log.Student.doWork1(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: java.lang.String test.log.Student.doWork2(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: protected java.lang.String test.log.Student.doWork3(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
如果把被代理类放到spring里面,则只能拦截到方法doWork1,其他方法拦截不到,为什么会有这种差异?
1. 注解类,用来注解哪些方法需要写日志
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyLog { }
2. 工厂类,由cglib生成被代理对象
public class ProxyFactory { private final static Callback DEFAULT_CALLBACK = new DefaultCallback(); private final static Log log = LogFactory.getLog(ProxyFactory.class); public static <T> T newInstance(Class<T> clazz) { return newInstance(clazz, DEFAULT_CALLBACK); } @SuppressWarnings("unchecked") public static <T> T newInstance(Class<T> clazz, Callback callback) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(clazz); enhancer.setCallback(callback); return (T) enhancer.create(); } private static class DefaultCallback implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { Object result = null; //只有标志了MyLog的方法才写日志 boolean flag = method.isAnnotationPresent(MyLog.class); if(flag){ log.debug("Method: " + method.toGenericString()); log.debug("params: " + JSON.toJSONString(args)); } // 调用方法 result = proxy.invokeSuper(obj, args); if(flag){ log.debug("result:" + JSON.toJSONString(result)); } return result; } } }
3.被代理的类
public class Student { public Student() { } public static Student newProxyInstance() { return ProxyFactory.newInstance(Student.class); } @MyLog public String doWork1(String name, int age) { return doWork2(name,age); } @MyLog String doWork2(String name, int age) { return doWork3(name,age); } @MyLog protected String doWork3(String name, int age) { return doWork4(name,age); } @MyLog private String doWork4(String name, int age) { return "姓名: " + name + ", 年龄: " + age; } }
4.测试类
public class Test { public static void main(String[] args) { Student stu = Student.newProxyInstance(); stu.doWork1("Xiao Zhang", 22); } }
5.结果输出:
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: public java.lang.String test.log.Student.doWork1(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: java.lang.String test.log.Student.doWork2(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: protected java.lang.String test.log.Student.doWork3(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
如果把被代理类放到spring里面,则只能拦截到方法doWork1,其他方法拦截不到,为什么会有这种差异?
spring内部实现的问题
可以看看我之前回复的
http://www.iteye.com/topic/1125911#2368327
回答神速啊,拜读啦。。。
里面有个问题,他那个setSelf(ServiceA self)是怎么注入的
public void setSelf(ServiceA self) { this.self = self; }
我在我自己的Service直接用@Autowired报错,代码片段如下
public class UserService extends BaseService{ private UserService self; @Autowired public void setSelf(UserService self) { this.self = self; }
没找到匹配类型!错误信息:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'studentController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.oy.service.UserService com.oy.controller.StudentController.userService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void com.oy.service.UserService.setSelf(com.oy.service.UserService); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.oy.service.UserService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
其实我要说的意思是这里的setSelf是类,而不是接口,这样可以吗?我尝试了,如果是类会报错,接口没问题。
8 楼
yangpeihai
2012-12-06
jinnianshilongnian 写道
yangpeihai 写道
哥们,请教个问题,为什么spring使用cglib动态代理没法拦截被代理类的所有非private方法,而我自己写的由cglib生成的代理类却可以拦截到被代理类的所有非private方法呢?,先道声谢谢,下面贴代码:
1. 注解类,用来注解哪些方法需要写日志
2. 工厂类,由cglib生成被代理对象
3.被代理的类
4.测试类
5.结果输出:
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: public java.lang.String test.log.Student.doWork1(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: java.lang.String test.log.Student.doWork2(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: protected java.lang.String test.log.Student.doWork3(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
如果把被代理类放到spring里面,则只能拦截到方法doWork1,其他方法拦截不到,为什么会有这种差异?
1. 注解类,用来注解哪些方法需要写日志
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyLog { }
2. 工厂类,由cglib生成被代理对象
public class ProxyFactory { private final static Callback DEFAULT_CALLBACK = new DefaultCallback(); private final static Log log = LogFactory.getLog(ProxyFactory.class); public static <T> T newInstance(Class<T> clazz) { return newInstance(clazz, DEFAULT_CALLBACK); } @SuppressWarnings("unchecked") public static <T> T newInstance(Class<T> clazz, Callback callback) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(clazz); enhancer.setCallback(callback); return (T) enhancer.create(); } private static class DefaultCallback implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { Object result = null; //只有标志了MyLog的方法才写日志 boolean flag = method.isAnnotationPresent(MyLog.class); if(flag){ log.debug("Method: " + method.toGenericString()); log.debug("params: " + JSON.toJSONString(args)); } // 调用方法 result = proxy.invokeSuper(obj, args); if(flag){ log.debug("result:" + JSON.toJSONString(result)); } return result; } } }
3.被代理的类
public class Student { public Student() { } public static Student newProxyInstance() { return ProxyFactory.newInstance(Student.class); } @MyLog public String doWork1(String name, int age) { return doWork2(name,age); } @MyLog String doWork2(String name, int age) { return doWork3(name,age); } @MyLog protected String doWork3(String name, int age) { return doWork4(name,age); } @MyLog private String doWork4(String name, int age) { return "姓名: " + name + ", 年龄: " + age; } }
4.测试类
public class Test { public static void main(String[] args) { Student stu = Student.newProxyInstance(); stu.doWork1("Xiao Zhang", 22); } }
5.结果输出:
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: public java.lang.String test.log.Student.doWork1(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: java.lang.String test.log.Student.doWork2(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: protected java.lang.String test.log.Student.doWork3(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
如果把被代理类放到spring里面,则只能拦截到方法doWork1,其他方法拦截不到,为什么会有这种差异?
spring内部实现的问题
可以看看我之前回复的
http://www.iteye.com/topic/1125911#2368327
回答神速啊,拜读啦。。。
里面有个问题,他那个setSelf(ServiceA self)是怎么注入的
public void setSelf(ServiceA self) { this.self = self; }
我在我自己的Service直接用@Autowired报错,代码片段如下
public class UserService extends BaseService{ private UserService self; @Autowired public void setSelf(UserService self) { this.self = self; }
没找到匹配类型!错误信息:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'studentController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.oy.service.UserService com.oy.controller.StudentController.userService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void com.oy.service.UserService.setSelf(com.oy.service.UserService); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.oy.service.UserService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
7 楼
jinnianshilongnian
2012-12-06
yangpeihai 写道
哥们,请教个问题,为什么spring使用cglib动态代理没法拦截被代理类的所有非private方法,而我自己写的由cglib生成的代理类却可以拦截到被代理类的所有非private方法呢?,先道声谢谢,下面贴代码:
1. 注解类,用来注解哪些方法需要写日志
2. 工厂类,由cglib生成被代理对象
3.被代理的类
4.测试类
5.结果输出:
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: public java.lang.String test.log.Student.doWork1(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: java.lang.String test.log.Student.doWork2(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: protected java.lang.String test.log.Student.doWork3(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
如果把被代理类放到spring里面,则只能拦截到方法doWork1,其他方法拦截不到,为什么会有这种差异?
1. 注解类,用来注解哪些方法需要写日志
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyLog { }
2. 工厂类,由cglib生成被代理对象
public class ProxyFactory { private final static Callback DEFAULT_CALLBACK = new DefaultCallback(); private final static Log log = LogFactory.getLog(ProxyFactory.class); public static <T> T newInstance(Class<T> clazz) { return newInstance(clazz, DEFAULT_CALLBACK); } @SuppressWarnings("unchecked") public static <T> T newInstance(Class<T> clazz, Callback callback) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(clazz); enhancer.setCallback(callback); return (T) enhancer.create(); } private static class DefaultCallback implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { Object result = null; //只有标志了MyLog的方法才写日志 boolean flag = method.isAnnotationPresent(MyLog.class); if(flag){ log.debug("Method: " + method.toGenericString()); log.debug("params: " + JSON.toJSONString(args)); } // 调用方法 result = proxy.invokeSuper(obj, args); if(flag){ log.debug("result:" + JSON.toJSONString(result)); } return result; } } }
3.被代理的类
public class Student { public Student() { } public static Student newProxyInstance() { return ProxyFactory.newInstance(Student.class); } @MyLog public String doWork1(String name, int age) { return doWork2(name,age); } @MyLog String doWork2(String name, int age) { return doWork3(name,age); } @MyLog protected String doWork3(String name, int age) { return doWork4(name,age); } @MyLog private String doWork4(String name, int age) { return "姓名: " + name + ", 年龄: " + age; } }
4.测试类
public class Test { public static void main(String[] args) { Student stu = Student.newProxyInstance(); stu.doWork1("Xiao Zhang", 22); } }
5.结果输出:
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: public java.lang.String test.log.Student.doWork1(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: java.lang.String test.log.Student.doWork2(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: protected java.lang.String test.log.Student.doWork3(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
如果把被代理类放到spring里面,则只能拦截到方法doWork1,其他方法拦截不到,为什么会有这种差异?
spring内部实现的问题
可以看看我之前回复的
http://www.iteye.com/topic/1125911#2368327
6 楼
yangpeihai
2012-12-06
哥们,请教个问题,为什么spring使用cglib动态代理没法拦截被代理类的所有非private方法,而我自己写的由cglib生成的代理类却可以拦截到被代理类的所有非private方法呢?,先道声谢谢,下面贴代码:
1. 注解类,用来注解哪些方法需要写日志
2. 工厂类,由cglib生成被代理对象
3.被代理的类
4.测试类
5.结果输出:
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: public java.lang.String test.log.Student.doWork1(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: java.lang.String test.log.Student.doWork2(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: protected java.lang.String test.log.Student.doWork3(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
如果把被代理类放到spring里面,则只能拦截到方法doWork1,其他方法拦截不到,为什么会有这种差异?
1. 注解类,用来注解哪些方法需要写日志
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyLog { }
2. 工厂类,由cglib生成被代理对象
public class ProxyFactory { private final static Callback DEFAULT_CALLBACK = new DefaultCallback(); private final static Log log = LogFactory.getLog(ProxyFactory.class); public static <T> T newInstance(Class<T> clazz) { return newInstance(clazz, DEFAULT_CALLBACK); } @SuppressWarnings("unchecked") public static <T> T newInstance(Class<T> clazz, Callback callback) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(clazz); enhancer.setCallback(callback); return (T) enhancer.create(); } private static class DefaultCallback implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { Object result = null; //只有标志了MyLog的方法才写日志 boolean flag = method.isAnnotationPresent(MyLog.class); if(flag){ log.debug("Method: " + method.toGenericString()); log.debug("params: " + JSON.toJSONString(args)); } // 调用方法 result = proxy.invokeSuper(obj, args); if(flag){ log.debug("result:" + JSON.toJSONString(result)); } return result; } } }
3.被代理的类
public class Student { public Student() { } public static Student newProxyInstance() { return ProxyFactory.newInstance(Student.class); } @MyLog public String doWork1(String name, int age) { return doWork2(name,age); } @MyLog String doWork2(String name, int age) { return doWork3(name,age); } @MyLog protected String doWork3(String name, int age) { return doWork4(name,age); } @MyLog private String doWork4(String name, int age) { return "姓名: " + name + ", 年龄: " + age; } }
4.测试类
public class Test { public static void main(String[] args) { Student stu = Student.newProxyInstance(); stu.doWork1("Xiao Zhang", 22); } }
5.结果输出:
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: public java.lang.String test.log.Student.doWork1(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: java.lang.String test.log.Student.doWork2(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: Method: protected java.lang.String test.log.Student.doWork3(java.lang.String,int)
[12/06 14:47:52] [DEBUG] ProxyFactory: params: ["Xiao Zhang",22]
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
[12/06 14:47:52] [DEBUG] ProxyFactory: result:"姓名: Xiao Zhang, 年龄: 22"
如果把被代理类放到spring里面,则只能拦截到方法doWork1,其他方法拦截不到,为什么会有这种差异?
5 楼
jinnianshilongnian
2012-12-05
yangpeihai 写道
哥们,请教个aop问题,如果使用cglib动态代理目标对象,是否可以拦截到目标对象的所有非private方法?请看下面:
下面是我的service代码片段
下面是我的application*.xml配置:
调试时,被代理的类又出现CGLIB字样,说明是CGLIB动态代理生成的类
现在问题是:接口方法findAll()访问时可以被拦截到,但是两个非接口测试方法调用时没有被拦截到,是不是我哪里配置少啦,指点下,多谢!
下面是我的service代码片段
[color=red]//公开的接口方法[/color] @AutoWriteLog public List findAll() { return test1("杨培海"); } [color=red]//自己测试用的方法test1[/color] @AutoWriteLog public List test1(String arg){ return test2(arg); } [color=red]//自己测试用的方法test2[/color] @AutoWriteLog List test2(String arg){ return userDao.findAll(); }
下面是我的application*.xml配置:
<aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 配置哪些类的方法需要进行事务管理 --> <aop:config proxy-target-class="true"> <aop:pointcut id="allManagerMethod" expression="execution(* com.oy.service.*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod" /> <!-- 配置aspect切面类 --> <aop:aspect ref="aspect"> <!-- 配置advice,即Aspect类中的logging()方法,这里采用在业务方法执行前进行拦截 --> <!-- <aop:before method="logging" pointcut-ref="allManagerMethod" /> <aop:after method="loggout" pointcut-ref="allManagerMethod" /> --> <aop:around pointcut-ref="allManagerMethod" method="myPointCutTest"/> </aop:aspect> </aop:config>
调试时,被代理的类又出现CGLIB字样,说明是CGLIB动态代理生成的类
org.springframework.aop.framework.[color=red]Cglib[/color]2AopProxy$DynamicAdvisedInterceptor@ec596
现在问题是:接口方法findAll()访问时可以被拦截到,但是两个非接口测试方法调用时没有被拦截到,是不是我哪里配置少啦,指点下,多谢!
@AutoWriteLog
public List test1(String arg){
return test2(arg);
}
这样调用不行
原因见
http://jinnianshilongnian.iteye.com/blog/1487235
4 楼
yangpeihai
2012-12-05
哥们,请教个aop问题,如果使用cglib动态代理目标对象,是否可以拦截到目标对象的所有非private方法?请看下面:
下面是我的service代码片段
下面是我的application*.xml配置:
调试时,被代理的类又出现CGLIB字样,说明是CGLIB动态代理生成的类
现在问题是:接口方法findAll()访问时可以被拦截到,但是两个非接口测试方法调用时没有被拦截到,是不是我哪里配置少啦,指点下,多谢!
下面是我的service代码片段
[color=red]//公开的接口方法[/color] @AutoWriteLog public List findAll() { return test1("杨培海"); } [color=red]//自己测试用的方法test1[/color] @AutoWriteLog public List test1(String arg){ return test2(arg); } [color=red]//自己测试用的方法test2[/color] @AutoWriteLog List test2(String arg){ return userDao.findAll(); }
下面是我的application*.xml配置:
<aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 配置哪些类的方法需要进行事务管理 --> <aop:config proxy-target-class="true"> <aop:pointcut id="allManagerMethod" expression="execution(* com.oy.service.*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod" /> <!-- 配置aspect切面类 --> <aop:aspect ref="aspect"> <!-- 配置advice,即Aspect类中的logging()方法,这里采用在业务方法执行前进行拦截 --> <!-- <aop:before method="logging" pointcut-ref="allManagerMethod" /> <aop:after method="loggout" pointcut-ref="allManagerMethod" /> --> <aop:around pointcut-ref="allManagerMethod" method="myPointCutTest"/> </aop:aspect> </aop:config>
调试时,被代理的类又出现CGLIB字样,说明是CGLIB动态代理生成的类
org.springframework.aop.framework.[color=red]Cglib[/color]2AopProxy$DynamicAdvisedInterceptor@ec596
现在问题是:接口方法findAll()访问时可以被拦截到,但是两个非接口测试方法调用时没有被拦截到,是不是我哪里配置少啦,指点下,多谢!
3 楼
gaiqiliang
2012-09-27
![](/images/smiles/icon_biggrin.gif)
![](/images/smiles/icon_biggrin.gif)
![](/images/smiles/icon_idea.gif)
2 楼
jinnianshilongnian
2012-09-26
fatmonkey64 写道
跟进开涛 哥
![](/images/smiles/icon_idea.gif)
![](/images/smiles/icon_biggrin.gif)
1 楼
fatmonkey64
2012-09-26
跟进开涛 哥
![](/images/smiles/icon_idea.gif)
发表评论
-
一段Spring代码引起的调用绑定总结
2014-03-04 07:41 15319代码 @Component public class B ... -
一段Spring代码引起的调用绑定总结
2014-03-02 10:53 0代码 @Component public class ... -
Spring Cache抽象详解
2014-01-08 07:54 150942缓存简介 缓存,我的理解是:让数据更接近于使 ... -
Spring3.1新属性管理API:PropertySource、Environment、Profile
2014-01-07 08:05 72895Spring3.1提供了新的属性管理API,而且功能非常强 ... -
Spring3.1新属性管理API:PropertySource、Environment、Profile
2014-01-07 08:04 0Spring3.1提供了新的属性管理API,而且功能非常强 ... -
Spring动态部署Bean/Controller/Groovy Controller
2014-01-06 08:00 24387最近有好几个咨询如何动态部署Bean/动态部署Spring ... -
Spring4新特性——注解、脚本、任务、MVC等其他特性改进
2013-12-25 07:58 68576Spring4新特性——泛型限定式依赖注入 Spring ... -
Spring4新特性——JSR310日期时间API的支持
2013-12-24 07:48 39310Spring4新特性——泛型限定式依赖注入 Spring ... -
Spring3.1新属性管理API:PropertySource、Environment、Profile
2013-12-23 21:44 0Spring3.1提供了新的属性管理API,而且功能非常强 ... -
Spring4新特性——更好的Java泛型操作API
2013-12-23 07:43 41872Spring4新特性——泛型限定式依赖注入 Spring ... -
Spring4新特性——Groovy Bean定义DSL
2013-12-19 07:33 37660Spring4新特性——泛型限定式依赖注入 Spring ... -
Spring4新特性——Groovy Bean定义DSL
2013-12-18 20:53 0Spring4支持使用Groovy DSL来进行Bean定 ... -
Spring4新特性——集成Bean Validation 1.1(JSR-349)到SpringMVC
2013-12-16 08:10 157960Spring4新特性——泛型限定式依赖注入 Spring ... -
Spring4新特性——集成Bean Validation 1.1(JSR-349)到SpringMVC
2013-12-15 10:51 0在之前的《跟我学SpringMVC》中的《第七章 注解式控 ... -
Spring4新特性——Web开发的增强
2013-12-14 08:12 270418Spring4新特性——泛型限定式依赖注入 Spring ... -
Spring4新特性——核心容器的其他改进
2013-12-14 07:23 47644Spring4新特性——泛型限定式依赖注入 Spring ... -
Spring4新特性——核心容器的其他改进
2013-12-13 22:54 311接上一篇《Spring4新特性——泛型限定式依赖注入》,接 ... -
Spring4新特性——泛型限定式依赖注入
2013-12-13 20:46 119440Spring4新特性——泛型限定式依赖注入 Spring ... -
Spring事务超时时间可能存在的错误认识
2013-12-06 09:36 475641、先看代码 1.1、spring-config.xml ... -
采用共享jar包部署struts2+spring集成项目会遇到的问题
2013-11-29 06:45 6330比如tomcat下边有个lib,放着我们需要的struts2 ...
相关推荐
总结来说,Spring对DAO的支持显著提高了代码的可读性和可维护性,降低了系统组件间的耦合,并通过提供对JDBC和Hibernate的抽象,使得数据访问变得更加简单和安全。这种支持鼓励开发者采用面向接口的编程风格,有利于...
2. **分层设计**:Spring框架支持分层的设计模式,这意味着不同的业务功能可以被封装在不同的层中,例如Web层负责处理用户界面,Service层处理业务逻辑,DAO层处理数据访问。这样的设计有助于保持代码的清晰度,并...
总结来说,Spring通过其丰富的DAO支持,降低了数据访问层的复杂性,提高了代码的可读性和可维护性。开发者只需要关注业务逻辑,而无需深陷于底层数据访问的细节。通过合理使用Spring提供的jar包,可以构建高效、稳定...
8. **Unit Testing**: Spring提供了一些工具,如`@TransactionalTest`注解和`MockMvc`,方便对DAO层进行单元测试,确保代码质量。 在实际应用中,Spring DAO模式的实现通常会结合使用上述组件,通过配置文件(XML或...
通过这种方式,上层的应用程序可以无需直接处理复杂的数据库操作,只需调用DAO层提供的接口即可完成数据交互。 #### 2. Spring框架的支持 Spring框架提供了丰富的特性来支持DAO模式的实现,包括但不限于: - **...
DAO层的主要任务是提供对数据库的操作接口,包括增删查改等基本操作,同时处理SQL语句的编写、事务管理以及异常处理。通过这种方式,业务层可以专注于业务逻辑,而无需关心底层数据访问的实现。 2. 设计模式 DAO...
在Struts2+Hibernate+Spring的集成中,泛型DAO扮演着重要的角色,它使得DAO层对所有实体类的操作变得统一和规范。 首先,让我们详细了解一下Struts2。Struts2是基于拦截器的MVC框架,它提供了强大的动作映射、结果...
— spring对DAO层的事务代理 --> <bean id="companyDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> *">PROPAGATION_REQUIRED *">PROPAGATION_...
- **DAO层类图**(图27.13):展示了DAO层中的关键类,包括ManagerDAO、AccountDAO、EmployeeDAO等。这些DAO类实现了各自对应的接口,并继承自_BaseRootDAO类。_BaseRootDAO类封装了一系列通用的数据访问方法,并...
《Spring JDBC DAO详解》 ...总结,Spring JDBC DAO模式通过Spring框架提供的工具和设计模式,极大地简化了数据库操作,提高了开发效率。了解并掌握这一模式,对于提升Java后端开发能力具有重要意义。
在本示例中,我们将探讨如何使用MyBatis连接到MySQL数据库并在Dao层进行数据处理。这对于初学者来说是一个很好的起点,可以帮助理解MyBatis的基础操作。 1. **MyBatis简介** MyBatis消除了几乎所有的JDBC代码和...
Spring框架基础总结 一、Spring框架概述 Spring框架是一个开源的控制反转(IoC)和面向切面(AOP)的容器框架,旨在简化企业级Java应用的开发工作。Spring框架的核心价值在于其分层架构设计,使得开发者可以根据...
- **泛型支持**: 由于Spring对泛型的支持有限,因此在DAO层封装时采用了泛型加抽象类的方式。具体来说,可以通过定义一个抽象类`BaseDaoSupport`来实现泛型支持,该抽象类包含了一些通用的方法和属性。 ```java ...
同时,JdbcDaoSupport和HibernateDaoSupport作为基础支持类,能帮助开发者快速构建符合Spring风格的DAO层。在实际开发中,结合Spring的其他特性,如AOP和IoC,可以进一步提高代码的可维护性和可测试性。
在Spring框架中,提供了对DAO的支持,例如通过事务管理、AOP(面向切面编程)来增强DAO的性能和安全性。Spring的JdbcTemplate和HibernateTemplate等工具类简化了DAO的实现,使得开发者可以更专注于业务逻辑而不是...
在实际开发中,Spring框架还提供了许多其他功能,如AOP(用于切面编程,实现如日志记录、事务管理等功能),MVC(用于构建Web应用),JDBC和ORM(如Hibernate、MyBatis)支持,以及Spring Boot(简化Spring应用的...
4. **数据访问对象(DAO)**:Spring提供了DAO支持,用于简化数据访问操作,包括数据库连接的创建、SQL语句的执行以及结果集的处理。 5. **事务处理**:Spring的事务管理模块提供了统一的事务处理策略,支持多种数据...
### Spring与数据库层整合的关键知识点 #### 一、Spring与持久化层的整合:O/R Mapping **O/R Mapping(对象关系映射)**是一种编程技术,用于将面向对象的应用程序中的数据转换成关系型数据库中的记录。在Java...
在本文中,我们将深入探讨如何整合Spring框架与iBatis数据访问对象(DAO)框架进行开发,基于提供的海威斯特公司的工程流程总结。Spring+iBatis的组合为开发者提供了强大的模型-视图-控制器(MVC)架构支持,以及...