ioc和aop扩展

2023-05-04 19:17:07 浏览数 (2)

ioc和aop扩展

构造注入

必须提供带参的构造函数

而且配置文件的标签也是不一样的

代码语言:javascript复制
public interface IUserDao {
    public  void add(User User);
}
public class UserDao implements IUserDao {
    @Override
    public void add(User User) {
​
        System.out.println("加了一个用户对象");
    }
}
public interface IUserservice {
​
    public void addUser(User User);
​
}
public class UserServices implements IUserservice{
    private UserDao dao;
    private String s1;
    private String s2;
    private int i;
​
    @Override
    public void addUser(User User) {
        dao.add(User);
    }
​
    public UserServices(UserDao dao, String s1, String s2, int i) {
        this.dao = dao;
        this.s1 = s1;
        this.s2 = s2;
        this.i = i;
    }
​
    public UserServices() {
    }
}
public class User implements java.io.Serializable {
    private Integer id; // 用户ID
    private String username; // 用户名
    private String password; // 密码
    private String email; // 电子邮件
​
    /* getter & setter */
    public Integer getId() {
        return id;
    }
​
    public void setId(Integer id) {
        this.id = id;
    }
​
    public String getUsername() {
        return username;
    }
​
    public void setUsername(String username) {
        this.username = username;
    }
​
    public String getPassword() {
        return password;
    }
​
    public void setPassword(String password) {
        this.password = password;
    }
​
    public String getEmail() {
        return email;
    }
​
    public void setEmail(String email) {
        this.email = email;
    }
​
}
public class HelloSpringTest {
​
  @Test
    public  void demo(){
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    IUserservice service = (IUserservice) ctx.getBean("userService");
    User user = new User();
    user.setId(1);
    user.setUsername("test");
    user.setPassword("123456");
    user.setEmail("test@xxx.com");
    service.addUser(user);
  }
​
}
代码语言:javascript复制
<?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="helloSpring" class="demo.HelloSpring">
        <property name="who">
            <value>Spring</value>
        </property>
    </bean>
    <bean id="userDao" class="dao.impl.UserDao">
​
    </bean>
    <bean id="userService" class="service.UserServices" >
        <constructor-arg>
        <ref bean="userDao"/>
    </constructor-arg>
        <constructor-arg index="1">
            <value >123</value>
        </constructor-arg>
        <constructor-arg index="3" type="int">
            <value >123</value>
        </constructor-arg>
        <constructor-arg index="2">
            <value >123</value>
        </constructor-arg>
    </bean>
    <bean id="loggerUntil" class="aop.LoggerUntil"/>
    <aop:config>
        <aop:pointcut id="pointcut"  expression="execution(  public void addUser(pojo.User))"/>
        <aop:aspect ref="loggerUntil">
            <aop:before method="before" pointcut-ref="pointcut"/>
            <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
        </aop:aspect>
    </aop:config>
   <!-- <aop:aspectj-autoproxy proxy-target-class="true"/>-->
</beans>
代码语言:javascript复制
<constructor-arg index="1" type="int">
    参数位置和参数类型
与设值注入进行对比
设值注入

通过setter访问器实现

灵活性好,但setter方法数量较多

时效性差

通过无参构造实例化

构造注入

通过构造方法实现

灵活性差,仅靠重载限制太多

时效性好

通过匹配的构造方法实例化,但建议保留无参构造

p命名空间

特点

使用属性而不是子元素的形式配置Bean的属性,从而简化了配置代码

用法

使用前要先要在Spring配置文件中引入p命名空间

代码语言:javascript复制
xmlns:p="http://www.springframework.org/schema/p"

对于直接量(基本数据类型、字符串)属性:p:属性名="属性值" 对于引用Bean的属性:p:属性名-ref="Bean的id"

代码语言:javascript复制
<bean id="user" class="pojo.User" p:email="1020222@qq.com" p:id="1" p:password="123" p:username="张三">
</bean>
​

注入不同数据类型

类型

方式

引用Bean

使用<ref>标签实现

注意bean属性和 local 属性的区别

使用内部Bean(其他地方都没法使用)

<property name="dao">

<bean class="dao.impl.UserDaoImpl"/></property>

注入集合类型的属性

分别使用<list>、<set>、<map>、<props>标签实现

注入null 和空字符串值

使用<null/>注入null 值

使用<value></value>注入空字符串值

注入直接量

使用<value>标签实现 注意特殊字符的处理

代码语言:javascript复制
<?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
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
    <bean id="entity" class="entity.TestEntity">
        <!-- 使用<![CDATA[]]>标记处理XML特 殊字符 -->
        <property name="specialCharacter1">
            <value><![CDATA[P&G]]></value>
        </property>
        <!-- 把XML特殊字符替换为实体引用 -->
        <property name="specialCharacter2">
            <value>P&amp;G</value>
        </property>
        <!-- 定义内部Bean -->
        <property name="innerBean">
            <bean class="entity.User">
                <property name="username">
                    <value>Mr. Inner</value>
                </property>
            </bean>
        </property>
        <!-- 注入List类型 -->
        <property name="list">
            <list>
                <!-- 定义List中的元素 -->
                <value>足球</value>
                <value>篮球</value>
            </list>
        </property>
        <!-- 注入数组类型 -->
        <property name="array">
            <list>
                <!-- 定义数组中的元素 -->
                <value>足球</value>
                <value>篮球</value>
            </list>
        </property>
        <!-- 注入Set类型 -->
        <property name="set">
            <set>
                <!-- 定义Set或数组中的元素 -->
                <value>足球</value>
                <value>篮球</value>
            </set>
        </property>
        <!-- 注入Map类型 -->
        <property name="map">
            <map>
                <!-- 定义Map中的键值对 -->
                <entry>
                    <key>
                        <value>football</value>
                    </key>
                    <value>足球</value>
                </entry>
                <entry>
                    <key>
                        <value>basketball</value>
                    </key>
                    <value>篮球</value>
                </entry>
            </map>
        </property>
        <!-- 注入Properties类型 -->
        <property name="props">
            <props>
                <!-- 定义Properties中的键值对 -->
                <prop key="football">足球</prop>
                <prop key="basketball">篮球</prop>
            </props>
        </property>
        <!-- 注入空字符串值 -->
        <property name="emptyValue">
            <value></value>
        </property>
        <!-- 注入null值 -->
        <property name="nullValue">
            <null/>
        </property>
    </bean>
</beans>
​
​

异常抛出增强

特点

在目标方法抛出异常时织入增强处理 可拔插的异常处理方案

代码语言:javascript复制
 public void throwex() throws Exception {
​
        throw new Exception("人造异常");
    }
    
public void afterThrowing(JoinPoint jp,Exception e){
        System.out.println("调用 "   jp.getTarget()   " 的 "   jp.getSignature().getName()
                  " 方法。方法入参:"   Arrays.toString(jp.getArgs()) e.getMessage());
        //log.info("" jp.getTarget() jp.getSignature()  Arrays.toString(jp.getArgs()));
    }  
代码语言:javascript复制
<aop:config>
        <aop:pointcut id="pointcut"  expression="execution(  public void *(..))"/>
        <aop:aspect ref="loggerUntil">
            <aop:before method="before" pointcut-ref="pointcut"/>
            <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"/>
        </aop:aspect>
    </aop:config>

最终增强

特点

无论方法是否抛出异常,都会在目标方法最后织入增强处理,即:该增强都会得到执行 类似于异常处理机制中finally块的作用,一般用于释放资源 可以为各功能模块提供统一的,可拔插的处理方案

用法与before类似

代码语言:javascript复制
<aop:after>

环绕增强

目标方法前后都可织入增强处理 功能最强大的增强处理 可获取或修改目标方法的参数、返回值,可对它进行异常处理,甚至可以决定目标方法是否执行

代码语言:javascript复制
<aop:around>
代码语言:javascript复制
public void around(ProceedingJoinPoint jp){
        System.out.println("调用 "   jp.getTarget()   " 的 "   jp.getSignature().getName()
                  " 方法。方法入参:"   Arrays.toString(jp.getArgs()));
        try {
             Object result = jp.proceed();
            System.out.println("调用 "   jp.getTarget()   " 的 "   jp.getSignature().getName()
                      " 方法。方法返回值:"   result);
        } catch (Throwable e) {
            System.out.println("调用 "   jp.getTarget()   " 的 "   jp.getSignature().getName()
                      " 方法。方法入参:"   Arrays.toString(jp.getArgs()) e.getMessage());
            e.printStackTrace();
        }finally {
            System.out.println("最终");
        }
    }

注解实现IOC

解释

注解方式将Bean的定义信息和Bean实现类结合在一起,简化配置

@Component:实现Bean组件的定义 @Repository :用于标注DAO类 @Service :用于标注业务类 @Controller :用于标注控制器类

代码语言:javascript复制
@Repository("userDao") 
public class UserDaoImpl implements UserDao {
    …
}
与在XML配置文件中编写
<bean id="userDao" 
class="dao.impl.UserDaoImpl" /> 
等效
​
使用注意事项

要在配置文件头部加相应信息,并且开启扫描

代码语言:javascript复制
<?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"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
​
       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
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    <bean id="helloSpring" class="demo.HelloSpring">
        <property name="who">
            <value>Spring</value>
        </property>
    </bean>
​
    <context:component-scan base-package="service,dao" />
​
​
​
​
</beans>
@Autowired

使用@Autowired注解实现Bean的自动装配,默认按类型匹配,可以使用@Qualifier指定Bean的名称

代码语言:javascript复制
@Service("userService")
public class UserServices implements IUserservice{
​
    @Autowired
    private UserDao dao;
​
​
    @Override
    public void addUser(User User) {
        dao.add(User);
    }
    public void throwex() throws Exception {
​
        throw new Exception("人造异常");
    }
    public UserServices(UserDao dao) {
​
    }
​
    public UserServices() {
    }
}
​
@Resource

注解实现组件装配,默认按名称匹配

代码语言:javascript复制
@Service("userService") 
public class UserServiceImpl implements UserService { 
    @Resource(name = "userDao")
    private UserDao dao; 
    …… 
}

注解配置切面

@Aspect

@Pointcut

@Before

@AfterReturning

@AfterThrowing

@Around

代码语言:javascript复制
@Component("loggerUntil")
@Aspect
public class LoggerUntil {
   private static Logger log = Logger.getLogger(LoggerUntil.class);
​
   @Pointcut("execution(* service.UserServices.*(..))")
   public void pointcut(){};
​
   @Before("pointcut()")
    public void before(JoinPoint jp){
        System.out.println("调用 "   jp.getTarget()   " 的 "   jp.getSignature().getName()
                  " 方法。方法入参:"   Arrays.toString(jp.getArgs()));
        //log.info("" jp.getTarget() jp.getSignature()  Arrays.toString(jp.getArgs()));
    }
    @AfterReturning(pointcut = "pointcut()",returning = "result")
    public void afterReturning(JoinPoint jp,Object result){
        System.out.println("调用 "   jp.getTarget()   " 的 "   jp.getSignature().getName()
                  " 方法。方法返回值:"   result);
        //log.info("" jp.getTarget() jp.getSignature() result);
    }
    @AfterThrowing(pointcut = "pointcut()",throwing = "e")
    public void afterThrowing(JoinPoint jp,Exception e){
        System.out.println("调用 "   jp.getTarget()   " 的 "   jp.getSignature().getName()
                  " 方法。方法入参:"   Arrays.toString(jp.getArgs()) e.getMessage());
        //log.info("" jp.getTarget() jp.getSignature()  Arrays.toString(jp.getArgs()));
    }
    @Around("pointcut()")
    public void around(ProceedingJoinPoint jp){
        System.out.println("调用 "   jp.getTarget()   " 的 "   jp.getSignature().getName()
                  " 方法。方法入参:"   Arrays.toString(jp.getArgs()));
        try {
             Object result = jp.proceed();
            System.out.println("调用 "   jp.getTarget()   " 的 "   jp.getSignature().getName()
                      " 方法。方法返回值:"   result);
        } catch (Throwable e) {
            System.out.println("调用 "   jp.getTarget()   " 的 "   jp.getSignature().getName()
                      " 方法。方法入参:"   Arrays.toString(jp.getArgs()) e.getMessage());
            e.printStackTrace();
        }finally {
            System.out.println("最终");
        }
    }
}
​
代码语言:javascript复制
<?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"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
​
       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
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    <bean id="helloSpring" class="demo.HelloSpring">
        <property name="who">
            <value>Spring</value>
        </property>
    </bean>
​
    <context:component-scan base-package="service,dao,aop" />
​
    <aop:aspectj-autoproxy />
​
​
​
</beans>

0 人点赞