天天看点

Spring注解开发,用JavaConfig配置spring 静态代理和动态代理,Spring实现aop使用注解开发使用JavaConfig配置spring代理模式AOP

使用注解开发

  1. 类的注入
@Component		//等价于<bean id="user" class="com.lyc.pojo.User"/> 
				//组件,放在类上,说明这个类被Spring管理了
 <!--指定要扫描的包,包下的注解就会生效-->
    <context:component-scan base-package="com.lyc.pojo"/>
           
  1. 属性的注入

    放在属性上方

    @value

    @Value("lyc")
    private String name;
    
    //等价于 <property name>
               
    1. @Component会按照mvc三层架构分层,实质上都是组件的装配
    • dao @Repository
    • service @Service
    • controller @Controller
@Scope("singleton")    //配置bean的作用域,声明这个类为单例模式
    					//等价于 bean scope标签
           

xml配置复杂的东西,注解适用于配置简单的东西

使用JavaConfig配置spring

不使用xml去配置

Javaconfig注册类到Spring

@Configuration
public class UserConfig {

    @Bean
    public User getUser(){
        return new User();
    }
}
           

测试类

@Test
    public void test2(){
        ApplicationContext context = new AnnotationConfigApplicationContext(UserConfig.class);
        User user = (User) context.getBean("getUser");

        System.out.println(user.getName());
    }
}
           

代理模式

分类

  • 静态代理
  • 动态代理

静态代理

  • 抽象角色:一般使用接口或者抽象类
  • 真实角色:被代理的角色
  • 代理角色:代理真实角色,有一些附属操作
  • 客户:真实使用资源的人

例子

接口

public interface Rent {
    public  void rent();
}
           

真实角色

public class Host  implements Rent{

    public void rent() {
        System.out.println("租房成功");
    }
}
           

代理角色

public class Proxy implements Rent{

    private Host host;
    public Proxy() {
    }
    public Proxy(Host host) {
        this.host = host;
    }
    public void rent() {
        host.rent();
    }
}
           

客户

public class Client {
    public static void main(String[] args) {
        Host host = new Host();
        Proxy proxy = new Proxy(host);
        proxy.rent();		//客户直接面对的是proxy
    }
}
           

好处

  • 使得真实角色的操作更加纯粹,不用去关注一些公共的业务
  • 公共业务交给代理角色
  • 公共业务发生扩展的时候,方便集中管理

静态代理缺点

  • 一个真实角色会产生一个代理角色,代码量会上去

动态代理

使用反射动态加载类,减少代码量

  • 抽象角色:一般使用接口或者抽象类
  • 真实角色:被代理的角色
  • 代理角色:代理真实角色,有一些附属操作,动态生成代理类
  • 客户:真实使用资源的人

动态分类

  • 基于接口的动态代理
  • 基于类的动态代理

Proxy:代理

InvocationHandler:产生代理类

万能工具类

//自动生产动态类
public class ProxyInvocationHandler implements InvocationHandler {


    //被代理的接口
    private Object target;

    public Object getTarget() {
        return target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }

    //生成得到代理类
    public  Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }


    //处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
        Object result = method.invoke(target, args);
        return result;
    }
    public void seeHouse(){
        System.out.println("看房子");
    }
}
           

通过传入对象不同,来分别加载对应的类,产生对应的代理类!

一个动态代理类代理一个接口

AOP

面向切面编程,通过预编译方式和运行期动态代理程序功能的统一维护的一种技术

在Spring中AOP

提供声明式事务;允许用户自定义切面

  • 横切关注点:跨越应用程序多个模块的方法或功能。即是与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点,如日志,安全,缓存,事务等等
  • 切面(Aspect):横切关注点被模块化的特殊对象,比如日志类
  • 通知(Adivice):切面必须要完成的工作,他是切面类中的一个方法,比如日志类中的方法
  • 目标(Target):被通知对象。一个接口或一个方法
  • 代理(Proxy):向目标对象应用通知之后创建的对象。比如生成的代理类
  • 切入点(PointCut):切面通知执行的地点的定义,比如invoke方法
  • 连接点(JointPoint):与切入点匹配的执行点
Spring注解开发,用JavaConfig配置spring 静态代理和动态代理,Spring实现aop使用注解开发使用JavaConfig配置spring代理模式AOP
Spring注解开发,用JavaConfig配置spring 静态代理和动态代理,Spring实现aop使用注解开发使用JavaConfig配置spring代理模式AOP

Spring5种类型的通知

Spring注解开发,用JavaConfig配置spring 静态代理和动态代理,Spring实现aop使用注解开发使用JavaConfig配置spring代理模式AOP

使用Spring原生api接口实现aop

一添加配置

<!--使用原生API接口-->
<!--配置aop:需要导入aop约束-->
<aop:config>
    <!--切入点 expression:表达式,execution(要执行的位置!)-->
    <!--限定符,类名,类下面的方法名,参数-->
    <aop:pointcut id="pointcut" expression="execution(public * com.lyc.service.UserServiceImpl.* (..))"/>

    <!--执行环绕-->
    <aop:advisor advice-ref="log" pointcut="pointcut" />
    <aop:advisor advice-ref="afterLog" pointcut="pointcut" />
</aop:config>
           

Userservice接口

public interface UserService {
    void add();
    void delete();
    void update();
    void select();
}
           

接口实现类

@Component
public class UserServiceImpl implements UserService{
    public void add() {
        System.out.println("增加了一个用户");
    }

    public void delete() {
        System.out.println("删除了一个用户");
    }

    public void update() {
        System.out.println("修改了一个用户");
    }

    public void select() {
        System.out.println("查询了一个用户");
    }
}
           

前置类型操作

@Component
public class Log implements MethodBeforeAdvice {

    /**
     *      method:要执行的目标对象的方法
     *      args:参数
     *      target:目标对象
     */
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+"的"+method.getName());
    }
}
           

后置返回操作

@Component
public class AfterLog implements AfterReturningAdvice {

    // o:返回值 objects:参数 o1:目标对象
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println(method.getName()+"返回结果为"+o);
    }
}
           

测试类

@Test
    public void test2(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        UserService userservice = (UserService) context.getBean("userServiceImpl");  //代理接口,但要获得接口实现类的bean

        userservice.add();

    }
}
           

使用自定义类去实现aop

配置文件

<!--方式二:自定义类-->
<aop:config>
    <aop:aspect ref="diyPointCut">
        <aop:pointcut id="pointcut" expression="execution(* com.lyc.service.UserServiceImpl.*(..))"/>
        <aop:before method="before" pointcut-ref="pointcut"/>
        <aop:after method="after" pointcut-ref="pointcut"/>
    </aop:aspect>

</aop:config>
           

自定义类

@Component
public class DiyPointCut {
    public void  before(){
        System.out.println("方法执行前");
    }
    public void  after(){
        System.out.println("方法执行后");
    }
}
           

注解实现AOP

配置文件

切面类

//使用注解方式实现AOP

@Component
@Aspect
public class AnnotationPointCut {

    @Before("execution(* com.lyc.service.UserServiceImpl.*(..))")		//定义切入点
    public void before(){
        System.out.println("方法执行前");
    }
}
 void  after(){
        System.out.println("方法执行后");
    }
}
           

注解实现AOP

配置文件

切面类

//使用注解方式实现AOP

@Component
@Aspect
public class AnnotationPointCut {

    @Before("execution(* com.lyc.service.UserServiceImpl.*(..))")		//定义切入点
    public void before(){
        System.out.println("方法执行前");
    }
}