JavaConfig
- 让Spring项目全权交给Java来做,拜托了xml配置文件
- JavaConfig是Spring的子项目,Spring4之后,成为了一个核心功能
环境搭建
- 创建新模块,选择Spring
- 创建文件夹config,配置UserBean
package com.bkms.config;
import com.bkms.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration//该注释修饰的也会交由Spring容器托管,因为该容器本身也是@Component
//@Configuration也是配置类,和beans.xml是一样的
@Import(MyConfig2.class)//导入MyConfig2的bean
public class MyConfig {
//@Bean注解就相当于在xml文件中的bean标签
//方法的名字就相当于bean标签中的id属性
//方法中的返回值就相当于bean标签中的class属性
@Bean
public User getUserInstance(){
return new User();//就是返回要注入到bean的对象
}
}
- 测试代码
import com.bkms.config.MyConfig;
import com.bkms.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User userInstance = (User) context.getBean("getUserInstance");
System.out.println(userInstance.getName());//null
}
}
- 这种JavaConfig配置方式在SpringBoot中随处可见
代理模式
- SpringAOP的底层
- SpringAOP和SpringMVC是很重要的知识点
- 分为静态代理和动态代理
静态代理模式
角色分析(以租房举例)
- 抽象角色(租房这个行为,用接口表示)
- 真实角色(就是房东)
- 代理角色(就是中介)
- 客户(就是要租房的人)
使用代理模式的好处
- 使真实角色操作更加纯粹,不用关注多余的业务
- 实现了业务的分工
- 公共业务需要扩展的时候,方便集中管理
使用代理模式的缺点
- 一个真是角色对应一个代理角色,真实角色多的话,代理角色会翻倍
public interface Rent {
public void rent();
}
public class Host implements Rent {
public void rent() {
System.out.println("house host sale");
}
}
public class Proxy implements Rent{
private Host host1;
public Proxy() { }
public Proxy(Host host1) {
this.host1 = host1;
}
public void rent() {
host.rent();
//add more code here...
}
}
public class Client {
public static void main(String[] args) {
Host host = new Host();
Proxy proxy = new Proxy(host);
proxy.rent();
}
}
静态代理示例代码
在调用某方法前输出日志,体现了面向AOP编程的思想
- 接口
package com.bkms.demo02;
public interface UserService {
public void add();
public void delete();
public void modify();
public void query();
}
- 接口实现类
package com.bkms.demo02;
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("add");
}
public void delete() {
System.out.println("delete");
}
public void modify() {
System.out.println("modify");
}
public void query() {
System.out.println("query");
}
}
- 代理
package com.bkms.demo02;
import java.lang.reflect.Method;
public class UserServiceProxy implements UserService {
private UserServiceImpl userService;
public void setUserService(UserServiceImpl userService) {
this.userService = userService;
}
public UserServiceProxy() {
}
/**
* 获取完整方法名称
* @param msg 方法名称
* @return
*/
public String getMethodName(String msg){
Class<UserServiceProxy> uClass = UserServiceProxy.class;
try {
Method m = uClass.getMethod(msg);
return m.toString();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
/**
* 打印日志方法
* @param msg 方法名称
*/
public void log(String msg){
System.out.println("use "+msg+" method");
}
/**
* 增删改查方法
*/
public void add() {
log(getMethodName("add"));
userService.add();
}
public void delete() {
log(getMethodName("delete"));
userService.delete();
}
public void modify() {
log(getMethodName("modify"));
userService.modify();
}
public void query() {
log(getMethodName("query"));
userService.query();
}
}
- 用户
package com.bkms.demo02;
public class Client {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
UserServiceProxy userServiceProxy = new UserServiceProxy();
userServiceProxy.setUserService(userService);
userServiceProxy.add();
}
}
动态代理模式
- 动态代理的代理类是动态生成的,不是直接写好的
- 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 基于接口:JDK动态代理
- 基于类:cglib
- java字节码实现:javasist
- 需要了解2个类
- Proxy:代理
- InvocationHandler:调用处理程序
- 动态代理的本质,是通过反射机制实现
- 集中管理,实现业务分工
- 一个动态代理代理的是一个接口,一般是对应的一类业务
动态代理示例代码
- 例1
//Host.java
package com.bkms.demo03;
public class Host implements Rent {
public void rent() {
System.out.println("sale house");
}
public void contract() {
System.out.println("contract");
}
}
//Rent.java
package com.bkms.demo03;
public interface Rent {
void rent();
void contract();
}
//ProxyInvocationHandler.java
package com.bkms.demo03;
import com.bkms.demo02.UserServiceProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
private UserServiceProxy usp = new UserServiceProxy();
public void setTarget(Object target) {
this.target = target;
}
/**
* 处理代理实例上的方法调用并返回结果
* @param proxy 调用该方法的代理实例
* @param method 代理实例上的接口方法的实例
* @param args 接口方法参数阵列
* @return 从代理实例上的方法调用返回的值
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//add agent code here
usp.log(usp.getMethodName(method.getName()));
return method.invoke(rent,args);
}
/**
* 生成代理对象实例
* @return
*/
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
}
}
//Client.java
package com.bkms.demo03;
public class Client {
public static void main(String[] args) {
//真实角色
Host host = new Host();
//代理角色
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//工厂生成代理类
pih.setRent(host);//这里实际上是多态,相当于Rent rent = new Host();
//获取代理类子类实例
Rent proxy = (Rent) pih.getProxy();
//调用
proxy.rent();
proxy.contract();
}
}
- 例2
package com.bkms.demo04;
import com.bkms.demo02.UserService;
import com.bkms.demo02.UserServiceImpl;
public class Client {
public static void main(String[] args) {
//真是角色
UserServiceImpl userService = new UserServiceImpl();
//代理类处理类
ProxyInvocationHandler handler = new ProxyInvocationHandler();
//设置代理
handler.setTarget(userService);
//动态生成代理类
UserService proxy = (UserService) handler.getProxy();
//调用真实角色的方法
proxy.modify();
}
}