我们一直使用ProxyFactoryBean来显式的创建AOP代理。但是在很多场合,这种方式将会使编写配置文件的工作量大大增加;由于要从ProxyFactoryBean获得代理对象,也会使应用和Spring之间的耦合度增加。下面介绍使用Spring提供的自动代理机制来解决这类问题。
1、使用BeanNameAutoProxyCreator
Spring提供的BeanNameAutoProxyCreator类允许我们通过Bean的name属性来指定代理的Bean。它暴露了java.lang.String[]类型的beanNames和 interceptorNames属性。beanNames可以指定被代理的Bean名字列表,支持“*”通配符,例如“*DAO”表示所有名字以“DAO”结尾的Bean。interceptorNames指定通知(Advice)列表,或者通知者(Advisor)列表。
下面通过一个例程来演示如何使用BeanNameAutoProxyCreator。在例子中,有两个Bean:TestBeanA和BeanB,并在TestMain类中的main方法中调用其MyMethod()方法。自动代理将会在方法调用前自动的执行配置的前置通知,输出提示信息。
新建一个名字为AOP_Test4.10的工程,添加Spring的IoC和AOP库后,新建一aop.test包,再分别创建两个类TestBeanA和BeanB,添加MyMethod()方法,代码如下:
代码 查看源代码copy to clipboard打印
/**
*
*/
package aop.test;
/**
* @author zhangyong
*
*/
public class TestBeanA {
public void MyMethod() {
System.out.println(this.getClass().getName()
+ ".MyMethod() is run!");
}
}
/**
*
*/
package aop.test;
/**
* @author zhangyong
*
*/
public class TestBeanA {
public void MyMethod() {
System.out.println(this.getClass().getName()
+ ".MyMethod() is run!");
}
}
代码 查看源代码copy to clipboard打印
/**
*
*/
package aop.test;
/**
* @author zhangyong
*
*/
public class BeanB {
public void MyMethod() {
System.out.println(this.getClass().getName()
+ ".MyMethod() is run!");
}
}
/**
*
*/
package aop.test;
/**
* @author zhangyong
*
*/
public class BeanB {
public void MyMethod() {
System.out.println(this.getClass().getName()
+ ".MyMethod() is run!");
}
}
再创建前置通知类BeforeAdvice:
代码 查看源代码copy to clipboard打印
/**
*
*/
package aop.test;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
/**
* @author zhangyong
*
*/
public class BeforeAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target)
throws Throwable {
System.out.println(method.getName() + "(),将要运行!");
}
}
/**
*
*/
package aop.test;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
/**
* @author zhangyong
*
*/
public class BeforeAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target)
throws Throwable {
System.out.println(method.getName() + "(),将要运行!");
}
}
最后创建含有main方法的测试类TestMain:
代码 查看源代码copy to clipboard打印
/**
*
*/
package aop.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author zhangyong
*
*/
public class TestMain {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext(
"applicationContext.xml");
TestBeanA beanA = (TestBeanA)ac.getBean("TestBeanA");
beanA.MyMethod();
BeanB beanB = (BeanB)ac.getBean("BeanB");
beanB.MyMethod();
}
}
/**
*
*/
package aop.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author zhangyong
*
*/
public class TestMain {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext(
"applicationContext.xml");
TestBeanA beanA = (TestBeanA)ac.getBean("TestBeanA");
beanA.MyMethod();
BeanB beanB = (BeanB)ac.getBean("BeanB");
beanB.MyMethod();
}
}
在配置文件中配置Bean和自动代理Bean,完成后代码如下:
代码 查看源代码copy to clipboard打印
<?xml version="1.0" encoding="UTF-8"?>
<beans …………>
<bean id="TestBeanA" class="aop.test.TestBeanA"/>
<bean id="BeanB" class="aop.test.BeanB"/>
<bean id="BeforeAdvice" class="aop.test.BeforeAdvice"></bean>
<bean class="org.springframework.aop.framework.autoproxy.
BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>Test*</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>BeforeAdvice</value>
</list>
</property>
</bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans …………>
<bean id="TestBeanA" class="aop.test.TestBeanA"/>
<bean id="BeanB" class="aop.test.BeanB"/>
<bean id="BeforeAdvice" class="aop.test.BeforeAdvice"></bean>
<bean class="org.springframework.aop.framework.autoproxy.
BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>Test*</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>BeforeAdvice</value>
</list>
</property>
</bean>
</beans>
运行主类,输出结果如下:
可以看到,在主类TestMain中,我们是直接从Spring IoC容器中获取收管Bean而不是像以前那样从ProxyFactoryBean中获取代理,但是我们的前置通知BeforeAdvice仍然在TestBeanA对象的MyMethod()方法执行前被触发,这说明我们的自动代理正在工作。
2、使用DefaultAdvisorAutoProxyCreator
DefaultAdvisorAutoProxyCreator允许我们只需定义相应的Advisor通知者,就可以完成自动代理。配置好DefaultAdvisorAutoProxyCreator受管Bean后,它会自动查找配置文件中定义的Advisor,并将它们作用于所有的Bean。
修改例程4.10的配置文件,使用DefaultAdvisorAutoProxyCreator来完成自动代理。完成后配置文件代码如下(本例完整工程代码见例程4.11):
代码 查看源代码copy to clipboard打印
<?xml version="1.0" encoding="UTF-8"?>
<beans ……>
<bean id="TestBeanA" class="aop.test.TestBeanA" />
<bean id="BeanB" class="aop.test.BeanB" />
<bean id="BeforeAdvice" class="aop.test.BeforeAdvice"/>
<bean class="org.springframework.aop.framework.autoproxy.
DefaultAdvisorAutoProxyCreator" />
<bean class="org.springframework.aop.support.NameMatchMethod
PointcutAdvisor">
<property name="advice" ref="BeforeAdvice" />
<property name="mappedNames">
<list>
<value>*Method*</value>
</list>
</property>
</bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans ……>
<bean id="TestBeanA" class="aop.test.TestBeanA" />
<bean id="BeanB" class="aop.test.BeanB" />
<bean id="BeforeAdvice" class="aop.test.BeforeAdvice"/>
<bean class="org.springframework.aop.framework.autoproxy.
DefaultAdvisorAutoProxyCreator" />
<bean class="org.springframework.aop.support.NameMatchMethod
PointcutAdvisor">
<property name="advice" ref="BeforeAdvice" />
<property name="mappedNames">
<list>
<value>*Method*</value>
</list>
</property>
</bean>
</beans>
运行主类输出结果如下:
分享到:
相关推荐
**Spring AOP 实现机制详解** Spring AOP(面向切面编程)是Spring框架的核心特性之一,它允许程序员在不修改源代码的情况下,通过“切面”来插入额外的业务逻辑,如日志、事务管理等。AOP的引入极大地提高了代码的...
当目标对象实现了至少一个接口时,Spring将使用JDK的动态代理机制。JDK动态代理通过实现InvocationHandler接口,并在运行时动态生成一个实现了目标对象所有接口的代理类。 - **JDK动态代理**:JDK的java.lang....
然而,如果需要更精细的控制,可以通过`@EnableAspectJAutoProxy`注解开启基于AspectJ的自动代理支持,或者通过`proxyTargetClass`属性来强制使用CGLIB代理。 总结一下,Spring的AOP机制通过JDK动态代理和CGLIB动态...
综上所述,通过理解Spring AOP的配置和动态代理机制,我们可以灵活地在项目中添加横切关注点,提升代码的模块化和可维护性。在实际开发中,结合使用XML配置、注解配置以及适当的动态代理策略,可以使AOP功能更好地...
总之,Spring AOP通过代理机制和通知机制,为开发者提供了一种优雅的方式,来处理那些横切关注点,提高了代码的复用性和模块化,降低了系统复杂性,使得业务逻辑更加清晰,提高了开发效率。无论是静态代理还是动态...
动态代理提供了创建代理对象的机制,而Spring AOP则是基于动态代理实现的面向切面编程框架,简化了在多处插入相同逻辑的复杂度。在实际开发中,理解并熟练运用这两个技术对于提高代码质量和可维护性至关重要。
- **自动代理生成**:Spring容器可以在启动时自动识别并生成代理对象,无需手动创建。 - **事务管理**:Spring AOP的一个常见应用就是声明式事务管理,通过`@Transactional`注解可以轻松地在方法级别控制事务。 综...
通过这个代理对象调用方法,Spring会自动插入预先定义好的通知逻辑。 总的来说,JDK动态代理是Spring AOP实现的基础,它允许我们在运行时动态创建代理对象,实现对方法调用的拦截和增强。Spring AOP则在此基础上...
5. **代理(Proxy)**:Spring AOP通过动态代理机制创建目标对象的代理,代理对象在调用目标方法时会自动插入切面逻辑。在Java项目中,Spring可以使用JDK动态代理或CGLIB动态代理来创建代理对象。 在实际应用中,...
CGLIB通常作为Spring AOP的默认代理机制,因为它可以处理未实现接口的类。 接下来,我们来探讨责任链模式。在Spring AOP中,每个切面(Aspect)都可以看作是责任链上的一个节点。当一个方法被调用时,这个调用会...
4. 使用注解驱动的AOP配置,以及如何在Spring配置文件中启用AOP自动代理。 5. 引入的概念和使用,以及如何通过引入增加类的方法或属性。 6. 实践示例,可能包括事务管理、日志记录等实际应用场景的AOP实现。 通过这...
Spring AOP基于两种代理机制实现:JDK动态代理和CGLIB代理。JDK动态代理适用于实现了接口的目标对象,通过反射机制创建一个代理类来拦截方法调用。而CGLIB是在运行时动态生成一个目标类的子类,从而实现对方法的...
Spring AOP在默认情况下使用JDK动态代理,但当目标类没有接口时,会自动切换到CGLib。通过动态代理,Spring可以在运行时创建代理对象,根据配置织入相应的切面逻辑,无需程序员手动创建和维护代理类。 总的来说,...
或者,在Spring Boot项目中,由于自动配置,通常不需要显式配置AOP代理。 总的来说,理解并正确配置Spring AOP的依赖,以及熟练掌握切面、通知和切入点的概念,对于有效利用Spring进行面向切面编程至关重要。通过...
通过本资料的学习,我们了解到Spring AOP是一种强大的工具,它通过代理机制有效地分离了业务逻辑与系统需求,极大地提升了系统的可维护性和扩展性。掌握Spring AOP的基本概念和实现方法对于开发高效、健壮的企业级...
6. **自动代理(Auto-proxy)**:Spring提供自动代理机制,可以通过配置或注解来自动识别哪些bean应该被代理。`@EnableAspectJAutoProxy`注解可以开启基于AspectJ的自动代理。 7. **注解驱动的AOP**:从Spring 2.5...
Spring AOP(面向切面编程)是Spring框架的一个重要组成部分,它允许开发者将...开发者无需手动编写代理类,Spring的AOP框架自动识别和应用配置中的AOP规则,大大简化了AOP的应用,并提高了代码的可维护性和可扩展性。
二、Spring AOP实现机制 Spring AOP通过动态代理来实现,主要有两种代理方式: 1. JDK动态代理:适用于实现了接口的目标对象,通过反射创建代理对象,代理对象在调用真实对象方法前/后执行通知。 2. CGLIB代理:...
package com.gc.autoproxy下为:aop方式自动代理 package com.gc.cglib下为:aop方式cglib代理 package com.gc.dynproxy下为:aop方式动态代理 package com.gc.javaproxy下为:java代理机制实现 package ...
2. **`ProxyFactoryBean`**:Spring AOP的主要代理工厂,用于创建JDK动态代理。 3. **`CglibAopProxy`**:使用CGLIB库创建代理对象,适用于无法使用JDK动态代理的情况(如目标对象未实现接口)。 #### 六、Spring ...