回炉重造------Spring的IOC和AOP

发布于:2024-05-21 ⋅ 阅读:(165) ⋅ 点赞:(0)

IOC

Bean创建默认是单例模式,只会创建一个bean对象。通过xml方式实现bean,其实就是通过反射来实现的,bean的创建先获取到类的Class对象默认通过无参构造进行对象的创建,然后再setter方法进行属性配置。把bean创建在容器当中

bean的使用ApplicationContext解析xml文件获取到Spring容器,此时bean对象已经创建好了,然后context.getbean()就可以拿到bean对象,就可以使用。

如果是有参构造,则通过<constructor-arg>去设置值

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.ioc.User">
        <constructor-arg index="0" value="李四"></constructor-arg>
        <constructor-arg name="name" value="lisi"></constructor-arg>
    </bean>

</beans>

spring的配置

bean的自动装配

使用注解的自动装配

@Autowired:先通过byType,再byName

@Resource:先byName,再byType

Spring注解开发

AOP

代理模式,AOP的底层

代理模式的分类:静态代理和动态代理

静态代理

例子一

这是租房子的动作。 

package com.ioc.Proxy;

//这是出租房子的动作
public interface Rent {
    public void rent();

}

 房东要出租房子,但是不想管其他的,就想交出钥匙和拿到房租

package com.ioc.Proxy;

//我这是房东,要出租房子
public class Host implements Rent{
    @Override
    public void rent() {
        System.out.println("我是房东,我要出租房子");
    }
}

代理对象来帮房东把房子租出去,并且把业务办好 

package com.ioc.Proxy;

//我是中介,我要帮房东出租房子,并且扩展业务
public class Proxy implements Rent{

    private Host host;

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

    @Override
    public void rent() {
        System.out.println("中介带我看房子");
        host.rent();
        System.out.println("中介带我签合同");
    }
}

我本来可以直接找房东,但是房东只想出租,所以我找代理让他带我租房子签合同 

package com.ioc.Proxy;

//这是我,我要找中介去找房子住
public class Myself {
    public static void main(String[] args) {

        Host host = new Host();
        Proxy proxy = new Proxy(host);
        proxy.rent();
        System.out.println("我找中介拿到了房子");
    }

}

例子二

对数据库的操作

package com.ioc.DBOP;

//对数据库的操作
public interface mapper {

    public void add();
    public void delete();
    public void update();
    public void query();
}

服务层实现接口,对数据库进行操作 

package com.ioc.DBOP;

//服务操作数据库
public class Service implements mapper{

    @Override
    public void add() {
        System.out.println("新增了数据");
    }

    @Override
    public void delete() {
        System.out.println("删除了数据");
    }

    @Override
    public void update() {
        System.out.println("更新了数据");
    }

    @Override
    public void query() {
        System.out.println("查询了数据");
    }
}

 这是代理,因为要输出日志,所以我来帮服务层操作数据库并且加入日志

package com.ioc.DBOP;

//现在我要在操作之后加入日志
public class Proxy implements mapper{

    private Service service;

    public void setService(Service service) {
        this.service = service;
    }

    @Override
    public void add() {
        service.add();
        System.out.println("我是代理,我加入增加日志");
    }

    @Override
    public void delete() {
        service.delete();
        System.out.println("我是代理,我加入删除日志");
    }

    @Override
    public void update() {
        service.update();
        System.out.println("我是代理,我加入更改日志");
    }

    @Override
    public void query() {
        service.query();
        System.out.println("我是代理,我加入查询日志");
    }
}

这是我,我在操作数据库的时候直接找服务去操作,但是我还想打印日志,所以我找代理 

package com.ioc.DBOP;

//我要去操作数据库,并且还要日志记录,我要去找代理给我打印日志
public class Myself {
    public static void main(String[] args) {
        Service service = new Service();

        Proxy proxy = new Proxy();
        proxy.setService(service);

        proxy.add();
        proxy.delete();
        proxy.update();
        proxy.query();
    }
}

动态代理(基于接口,基于类)

改写例子一

 租房的动作

package com.ioc.Proxy;

//这是出租房子的动作
public interface Rent {
    public void rent();

}

房东想要把房子出租出去 

package com.ioc.Proxy;

//我这是房东,要出租房子
public class Host implements Rent{
    @Override
    public void rent() {
        System.out.println("我是房东,我要出租房子");
    }
}

这是动态代理程序 ,getProxy()得到代理类,即得到中介,invoke()就是中介进行帮房东出租房子,并且进行功能增强。

package com.ioc.Proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//这个类自动生成代理类!!是一个处理程序
public class ProxyInvocationHandler implements InvocationHandler {

    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

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


    //处理代理实例,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("中介带我看房子");
        //代理的本质就是反射
        Object result = method.invoke(rent, args);
        System.out.println("交钱");
        return result;
    }
}

这就是我,我首先要知道谁在出租房子,然后我要去找到代理房东的中介,通过invocationhandler处理程序动态得到中介,并跟中介进行交接处理。

package com.ioc.Proxy;

//这是我,我要找中介去找房子住
public class Myself {
    public static void main(String[] args) {
        //真实的角色
        Host host = new Host();

        //代理角色 :现在还没有
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        //通过程序来处理调用的接口对象
        pih.setRent(host);
        //返回代理类,动态生成
        Rent proxy = (Rent) pih.getProxy();

        proxy.rent();
        System.out.println("我找中介拿到了房子");
    }

}

改写例子二

Spring实现AOP

通过注解实现AOP

package com.ioc.aoptest;

//动作接口
public interface Service {

    public void add();
    public void delete();
    public void update();
    public void query();
}
package com.ioc.aoptest;

public class Serviceimimpl implements Service{

    @Override
    public void add() {
        System.out.println("新增了数据");
    }

    @Override
    public void delete() {
        System.out.println("删除了数据");
    }

    @Override
    public void update() {
        System.out.println("更新了数据");
    }

    @Override
    public void query() {
        System.out.println("查询了数据");
    }
}

通过注解实现前置,后置,环绕通知,定义一个切面类

package com.ioc.aoptest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect  //标注这个类是一个切面
public class AnnotationPointCut {

    //前置通知
    @Before("execution(* com.ioc.aoptest.Serviceimimpl.*(..))")
    public void before(){
        System.out.println("前置通知!!!!-----");
    }

    //后置通知
    @After("execution(* com.ioc.aoptest.Serviceimimpl.*(..))")
    public void after(){
        System.out.println("后置通知!!!!-----");
    }

    @Around("execution(* com.ioc.aoptest.Serviceimimpl.*(..))")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前通知!!!!-----");

        Object proceed = joinPoint.proceed();

        System.out.println("环绕后通知!!!!-----");

    }
}

注册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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="service" class="com.ioc.aoptest.Serviceimimpl"></bean>
    <bean id="log" class="com.ioc.log.Log"></bean>
    <bean id="afterlog" class="com.ioc.log.AfterLog"></bean>


    <bean id="annotationPointCut" class="com.ioc.aoptest.AnnotationPointCut"></bean>
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

声明式事务

 


网站公告

今日签到

点亮在社区的每一天
去签到