顾问和注解

Posted chencheno

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了顾问和注解相关的知识,希望对你有一定的参考价值。

顾问包装通知

通知(advice)是Spring中的一种比较简单的切面,只能将切面织入到目标类的所有方法中,而无法对指定方法进行增强

顾问(advisor)是Spring提供的另外一种切面,可以织入到指定的方法中  

实现类:NameMatchMethodPointcutAdvisor(基于方法名称的增强顾问),RegexpMethodPointcutAdvice(基于正则表达式的增强顾问)

实例

接口

package com.spring.advisor;
/*业务接口*/
public interface IService {
    //业务方法
    public void doSome();

    public void say();
}

实现类

/*业务类*/
public class IServiceImpl implements IService{
    @Override
    public void doSome() {
        System.out.println("====真实业务===");
    }

    @Override
    public void say() {
        System.out.println("====say=====");
    }
}

增强类

/*增强类*/
public class MyAdvisor implements MethodBeforeAdvice, AfterReturningAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("===后置增强====");
    }

    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("====前置增强====");
    }
}

配置

NameMatchMethodPointcutAdvisor(基于方法名称的增强顾问)

<!--注入业务Bean-->
    <bean id="iServiceImpl" class="com.spring.advisor.IServiceImpl"></bean>
    <!--切面/通知-->
    <bean id="testBean" class="com.spring.advisor.TestBean"></bean>
   <bean id="myAdvisor" class="com.spring.advisor.MyAdvisor"></bean>
    <!--顾问包装通知-->
    <bean id="advisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
        <property name="advice" ref="myAdvisor"></property>
        <property name="mappedNames" value="*a*"></property>
    </bean>
    
    <bean id="proxyFactory" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="iServiceImpl"></property>
        <property name="interceptorNames" value="advisor"></property>
    </bean>

RegexpMethodPointcutAdvice(基于正则表达式的增强顾问)

 <!--注入业务Bean-->
    <bean id="iServiceImpl" class="com.spring.advisor.IServiceImpl"></bean>
    <!--切面/通知-->
    <bean id="testBean" class="com.spring.advisor.TestBean"></bean>
   <bean id="myAdvisor" class="com.spring.advisor.MyAdvisor"></bean>
    
   <!--顾问包装通知-->
    <bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <property name="advice" ref="myAdvisor"></property>
        <!--.代表单个字符
        *代表一项出现0-n次
        +代表前一项出现1-n次
        至少包含两个字符-->
        <property name="patterns">
            <list>
                <value>.*do.*</value>
            </list>
        </property>
    </bean>
    
    <bean id="proxyFactory" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="iServiceImpl"></property>
        <property name="interceptorNames" value="advisor"></property>
    </bean>

 

测试类

public class AdvisorTest {
    @Test
    public void advisorTest() {

        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取代理工厂Bean
        IService idoSomeServiceProxy = (IService) ctx.getBean("iServiceImpl");
        idoSomeServiceProxy.doSome();
        idoSomeServiceProxy.say();

    }
}

顾问代理生成器

 顾问代理生成器,当我们声明好顾问后为目标对象生成代理对象。如果项目中       存在多个代理对象的话,需要实例化许多的ProxyFactoryBean,我们可以使用顾       问   代理生成器来解决这个问题。  

        顾问代理生成器主要分两种

  • 自动顾问代理生成器:DefaultAdvisorAutoProxyCreator
  • 名称顾问代理生成器:BeanNameAutoProxyCreator

实例

接口

/*业务接口*/
public interface IService {
    //业务方法
    public void doSome();

    public void say();
}

实现类

/*业务类*/
public class IServiceImpl implements IService{
    @Override
    public void doSome() {
        System.out.println("====真实业务===");
    }

    @Override
    public void say() {
        System.out.println("====say=====");
    }
}

增强类

/*增强类*/
public class MyAdvisor implements MethodBeforeAdvice, AfterReturningAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("===后置增强====");
    }

    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("====前置增强====");
    }
}

配置

  • 自动顾问代理生成器:DefaultAdvisorAutoProxyCreator
  <!--注入业务Bean-->
    <bean id="iServiceImpl" class="com.spring.advisor.IServiceImpl"></bean>
    <!--切面/通知-->
    <bean id="testBean" class="com.spring.advisor.TestBean"></bean>
   <bean id="myAdvisor" class="com.spring.advisor.MyAdvisor"></bean>
    <!--顾问包装通知-->
    <!--<bean id="advisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
        <property name="advice" ref="myAdvisor"></property>
        <property name="mappedNames" value="*a*"></property>
    </bean>-->
   <!--顾问包装通知-->
    <bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <property name="advice" ref="myAdvisor"></property>
        <!--.代表单个字符
        *代表一项出现0-n次
        +代表前一项出现1-n次
        至少包含两个字符-->
        <property name="patterns">
            <list>
                <value>.*do.*</value>
            </list>
        </property>
    </bean>

    <!--默认顾问自动代理生成器-->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
  • 名称顾问代理生成器:BeanNameAutoProxyCreator
 <!--注入业务Bean-->
    <bean id="iServiceImpl" class="com.spring.advisor.IServiceImpl"></bean>
    <!--切面/通知-->
    <bean id="testBean" class="com.spring.advisor.TestBean"></bean>
   <bean id="myAdvisor" class="com.spring.advisor.MyAdvisor"></bean>
    <!--顾问包装通知-->
    <!--<bean id="advisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
        <property name="advice" ref="myAdvisor"></property>
        <property name="mappedNames" value="*a*"></property>
    </bean>-->
   <!--顾问包装通知-->
    <bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <property name="advice" ref="myAdvisor"></property>
        <!--.代表单个字符
        *代表一项出现0-n次
        +代表前一项出现1-n次
        至少包含两个字符-->
        <property name="patterns">
            <list>
                <value>.*do.*</value>
            </list>
        </property>
    </bean>
    
    <!--BeanName自动代理生成器-->
    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <!--配置BeanName-->
        <property name="beanNames" value="iServiceImpl,testBean"></property>
        <!--拦截顾问-->
        <property name="interceptorNames" value="advisor"></property>
    </bean>

IOC注解

配置

 <context:component-scan base-package="com.spring"/>

实体类

public class UserInfo implements Serializable {
    private Integer user_id;
    private String user_name;

    public Integer getUser_id() {
        return user_id;
    }

    public void setUser_id(Integer user_id) {
        this.user_id = user_id;
    }

    public String getUser_name() {
        return user_name;
    }

    public void setUser_name(String user_name) {
        this.user_name = user_name;
    }
}

Dao层接口

/**
 * Dao层接口
 */
public interface IUserInfoMapper {
    public int addUser(UserInfo info);
}

实现类

/**
 * Dao层标识   @Repository
 */
@Repository
public class IUserInfoMapperImpl implements IUserInfoMapper{
    @Override
    public int addUser(UserInfo info) {
        System.out.println("添加成功");
        return 1;
    }
}

测试类

public class iocTest {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext1.xml");
        IUserInfoService bean=(IUserInfoService)context.getBean("iUserInfoServiceImpl");
        bean.addUser(new UserInfo());
    }
}

输出

技术图片

 注释

/*业务类*/
@Service("IdoSomeService")
public class IdoSomeService {
    public void doSome(){
        System.out.println("业务类当中的doSome方法");
    }
    public void say(){
        System.out.println("业务类当中的say方法");
    }
}
@Pointcut("execution(* *..aop.*.do*(..))")
    public void pointCut(){

    }

       @Before("pointCut()")
    public void before(){
        System.out.println("==========前置增强==========");
    }
    @AfterReturning("pointCut()")
    public void after(){
        System.out.println("========后置增强=========");
    }

}

测试类

public class aopTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext1.xml");
        IdoSomeService bean = (IdoSomeService) context.getBean("IdoSomeService");
        bean.doSome();
        bean.say();
    }
}

输出

技术图片

 

使用注解方式实现Spring AOP  

  • 实现AOP的注解有
  • @Aspect 声明切面
  • @Ponitcut 声明公共的切点表达式
  • @Before 前置增强
  • @AfterReturning 后置增强
  • @Around 环绕增强
  • @AfterThrowing 异常抛出增强
  • @After 最终增强
/*业务类*/
@Service("IdoSomeService")
public class IdoSomeService {
    public void doSome(){
        System.out.println("业务类当中的doSome方法");
    }
    public void say(){
        System.out.println("业务类当中的say方法");
    }
}

增强类

/*增强类*/
@Aspect
@Component
public class MyAdvice {

    @Pointcut("execution(* *..aop.*.do*(..))")
    public void pointCut() {

    }

    @Before("pointCut()")
    public void before() {
        System.out.println("==========前置增强==========");
    }

    @AfterReturning("pointCut()")
    public void after() {
        System.out.println("========后置增强=========");
    }

    @After("pointCut()")
    public void doAfter() {
        System.out.println("======最终增强=======");
    }

    /*@AfterThrowing("pointCut()")
    public void doAfterThrowing() {
        System.out.println("======异常抛出增强=======");
    }*/

    @Around("pointCut()")
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
        /**
         * 环绕通知内部一定要确保执行该方法,如果不执行该方法,业务bean中被拦截的方法就不会被执行。
         * 当执行该方法,如果后面还有切面的话,它的执行顺序应该是这样的:先执行后面的切面,如果后面没有切面了,
         * 再执行最终的目标对象的业务方法。若不执行该方法,则后面的切面,业务bean的方法都不会被执行。
         */
        // if () { // 判断用户是否有权限,
        System.out.println("进入方法");
        Object result = pjp.proceed();
        System.out.println("退出方法");
        // }
        return result;
    }
}

@Pointcut("execution(* *..aop.*.do*(..))")
public void pointCut() {

}

@Before("pointCut()")
public void before() {
System.out.println("==========前置增强==========");
}

@AfterReturning("pointCut()")
public void after() {
System.out.println("========后置增强=========");
}

@After("pointCut()")
public void doAfter() {
System.out.println("======最终增强=======");
}

/*@AfterThrowing("pointCut()")
public void doAfterThrowing() {
System.out.println("======异常抛出增强=======");
}*/

@Around("pointCut()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
/**
* 环绕通知内部一定要确保执行该方法,如果不执行该方法,业务bean中被拦截的方法就不会被执行。
* 当执行该方法,如果后面还有切面的话,它的执行顺序应该是这样的:先执行后面的切面,如果后面没有切面了,
* 再执行最终的目标对象的业务方法。若不执行该方法,则后面的切面,业务bean的方法都不会被执行。
*/
// if () { // 判断用户是否有权限,
System.out.println("进入方法");
Object result = pjp.proceed();
System.out.println("退出方法");
// }
return result;
}

测试类

public class aopTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext1.xml");
        IdoSomeService bean = (IdoSomeService) context.getBean("IdoSomeService");
        bean.doSome();
        bean.say();
    }
}

 

以上是关于顾问和注解的主要内容,如果未能解决你的问题,请参考以下文章

Spring的Async注解线程池扩展方案

Hibernate注解常见错误

Spring笔记07(Spring AOP的通知advice和顾问advisor)

基于XML和注解的Spring定时器

翻译Ext JS升级顾问1.0发布

SAP PP顾问面试题及资料