我正在学习Spring,为了理解它是如何工作的,我创建了一个简单的项目。请在下面找到我项目的主要部分:
我的Spring-Customer.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<aop:aspectj-autoproxy />
<bean id="customerBoNoIterface" class="com.core.CustomerBoNoIterface" />
<!-- Aspect -->
<bean id="logAspect" class="com.aspect.LoggingAspect" />
</beans>请在我的AOP切入点下面找到:
@Before("execution(* com.core.CustomerBoNoIterface.addCustmer*(..))")
public void logBeforeDummy(JoinPoint joinPoint) {
System.out.println("hijacked : " + joinPoint.getSignature().getName());
System.out.println("******");
}请在我的课堂上找到CustomerBoNoIterface:
public class CustomerBoNoIterface {
private void addCustmerPrivate() {
System.out.println("calling addCustmerPrivate()");
}
public void addCustmerPublic() {
System.out.println("calling addCustmerPublic()");
}
protected void addCustmerProtected() {
System.out.println("calling addCustmerProtected()");
}
void addCustmerDefault() {
System.out.println("calling addCustmerDefault()");
}
public String addCustmerReturnString() {
System.out.println("calling addCustmerPublic return string");
return "";
}
}最后我的主要方法是:
public class App {
public static void main(String[] args) throws Exception {
ApplicationContext appContext = new ClassPathXmlApplicationContext("Spring-Customer.xml");
CustomerBoNoIterface customerBoNoIterfaceBean =appContext.getBean("customerBoNoIterface", CustomerBoNoIterface.class);
customerBoNoIterfaceBean.addCustmerPublic();
customerBoNoIterfaceBean.addCustmerDefault();
customerBoNoIterfaceBean.addCustmerProtected();
customerBoNoIterfaceBean.addCustmerReturnString();
}根据在线参考,Spring是由代理完成的,类需要实现一个接口,这样Spring才能编织方面,而且Spring只将方面编织到公共方法中。
但是,在我的例子中,我有一个没有接口的类,如上面的示例所示,我能够在以下方法中应用AOP:
customerBoNoIterfaceBean.addCustmerPublic();
customerBoNoIterfaceBean.addCustmerDefault();
customerBoNoIterfaceBean.addCustmerProtected();
customerBoNoIterfaceBean.addCustmerReturnString();因此,当我运行Main方法时,我在eclipse中的控制台中得到了以下输出:
hijacked : addCustmerPublic
******
calling addCustmerPublic()
hijacked : addCustmerDefault
******
calling addCustmerDefault()
hijacked : addCustmerProtected
******
calling addCustmerProtected()
hijacked : addCustmerReturnString
******
calling addCustmerPublic return string因此,我无法理解Spring是如何在公共方法之外的方法中编织方面的,而且也是一个没有接口的类?
提前谢谢你,
发布于 2013-11-30 07:40:21
在使用这些方法时,Spring使用反射API处理每个带注释的类,不会直接调用类的方法。因此,建议的方法的可见性在这里并不重要。
Spring提供了两种代理: 1)JDK代理:如果您的类实现至少一个接口,这个代理就会出现。
2)CGLIB代理:当您的类不实现任何接口时,这个代理就会出现。
在您的示例中,您的类不实现任何接口,因此您的类将通过使用CGLIB代理进行代理。
发布于 2013-11-30 07:25:23
来自春天的杜库:
Spring默认为AOP代理使用标准的J2SE动态代理。这使得任何接口(或一组接口)都能被代理。 Spring也可以使用CGLIB代理。这对于代理类来说是必要的,而不是接口。默认情况下,如果业务对象不实现接口,则使用CGLIB。由于编写接口而不是类是很好的实践,所以业务类通常会实现一个或多个业务接口。可以强制使用CGLIB,在这种情况下(希望很少),需要通知接口上没有声明的方法,或者需要将代理对象作为具体类型传递给方法。
只需阅读Spring文档就可以了,这绝对是很棒的。http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/
总之:您不需要仅仅为了使AOP成为可能而实现一个接口。如果不实现接口,则直接基于类生成CGLIB代理。其实我经常用这个。你确实需要在你的类路径上有一个小脑筋:http://mvnrepository.com/artifact/cglib/cglib/3.0
编辑一些关于我个人喜好的更多信息(很多人可能不同意)。在最近的几次中,我不再为所有东西编写接口。现在,我只在真正需要的时候才使用它们(例如,我有两个实现,比如用于测试),它确实加快了我的工作速度,简化了我的代码。使用带有文本替换等功能的现代IDE,如果您真的需要它,那么以后提取接口就不难了(对我来说非常罕见)。这只是我个人的看法。
https://stackoverflow.com/questions/20296883
复制相似问题