版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MASORL/article/details/82688923
因为不是很好理解,所以单独放在一章上来记录
看一下工作原理
示例代码
接口1
package com.spring.chapter4.addmethod;
public interface BeNotified {
void aspectStart();
void aspectStart(int b);
}
接口1实现
package com.spring.chapter4.addmethod;
import org.springframework.stereotype.Component;
@Component
public class BeNotifiedImpl implements BeNotified {
public void aspectStart() {
System.out.println("主体方法");
// throw new RuntimeException();
}
public void aspectStart(int b) {
}
}
接口2:
package com.spring.chapter4.addmethod;
public interface Encoreable {
void perfor();
}
接口2实现类
package com.spring.chapter4.addmethod;
import org.springframework.stereotype.Component;
@Component
public class EncoreableImpl implements Encoreable {
public void perfor() {
System.out.println("新增的方法!");
}
}
切面2
package com.spring.chapter4.addmethod;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class EncoreableIntroducer {
@DeclareParents(value = "com.spring.chapter4.addmethod.BeNotified+", defaultImpl = EncoreableImpl.class)
public static Encoreable encoreable;
}
测试
package com.spring.chapter4.addmethod;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AddmethodConfig.class)
public class AddmethodConfigTest {
@Autowired
private BeNotified beNotified;
@Test
public void test(){
System.out.println(beNotified instanceof Encoreable);
Encoreable beNotified = (Encoreable) this.beNotified;
beNotified.perfor();
}
}
测试结果
true
新增的方法!
打个断电看下beNotfied到底是个啥
注意红框:
(1)第一个红框,$Proxy,首先说明第一点,这个类,是一个代理。也就验证了spring aop是通过代理来封装目标对象
(2)第二个红框,targeSource指向了BeNotifiledImpl.也就是封装的目标对象
(3)第三个红框,查看它的接口,很明显,它除了继承了BeNotified接口,还继承了Encoreable。
一脸懵逼,看一下官方对@DeclareParents的解释
第一句话翻译过来的意思大概是:
Intrductions(在AspectJ中称为类型间声明),通过一个切面来声明访问对象实现给定接口,并代表这些对象提供该接口的实现。
换句话说,@DeclareParents可以通过切面为目标对象添加一个接口,并且提供这个对象的实例。
也就是我们在断点看到的。
xml方式配置
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="beNotified" class="com.spring.chapter4.xmladdmethod.BeNotifiedImpl"/>
<aop:config>
<aop:aspect>
<aop:declare-parents
types-matching="com.spring.chapter4.xmladdmethod.BeNotified+"
implement-interface="com.spring.chapter4.xmladdmethod.Encoreable"
default-impl="com.spring.chapter4.xmladdmethod.EncoreableImpl"/>
</aop:aspect>
</aop:config>
</beans>
或者也可以通过delegate-ref来引入一个bean
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="beNotified" class="com.spring.chapter4.xmladdmethod.BeNotifiedImpl"/>
<bean id="encoreable" class="com.spring.chapter4.xmladdmethod.EncoreableImpl"/>
<!--<aop:config>-->
<!--<aop:aspect>-->
<!--<aop:declare-parents-->
<!--types-matching="com.spring.chapter4.xmladdmethod.BeNotified+"-->
<!--implement-interface="com.spring.chapter4.xmladdmethod.Encoreable"-->
<!--default-impl="com.spring.chapter4.xmladdmethod.EncoreableImpl"/>-->
<!--</aop:aspect>-->
<!--</aop:config> -->
<aop:config>
<aop:aspect>
<aop:declare-parents
types-matching="com.spring.chapter4.xmladdmethod.BeNotified+"
implement-interface="com.spring.chapter4.xmladdmethod.Encoreable"
delegate-ref="encoreable"/>
</aop:aspect>
</aop:config>
</beans>